I am unable to send email to recipient with Field Locators - java

I am not able to send email(s), I've tried with my real email and I haven't received any emails. How do I get this to work? I am not getting any errors.
Doesn't Docusign have a clean working java example on how to send a PDF file with Field Locator(s) to be signed by recipient. I got this sample code from Docusign:
// Enter your DocuSign credentials
String UserName = "myUserName#hotmail.com";
String Password = "MyPassword";
String IntegratorKey = "c8ad614b-def7-4631-aede-c90e68ef84d4";
// specify a document we want signed
String SignTest1File = "C:/Users/Public/test/TEST.PDF";
// enter recipient (signer) name and email
String recipientName = "Recipient Name";
String recipientEmail = "RecipientEmail#yahoo.com";
// for production environment update to "www.docusign.net/restapi"
String BaseUrl = "https://demo.docusign.net/restapi";
// initialize the api client for the desired environment
ApiClient apiClient = new ApiClient();
apiClient.setBasePath(BaseUrl);
// create JSON formatted auth header
String creds = "{\"Username\":\"" + UserName + "\",\"Password\":\"" + Password + "\",\"IntegratorKey\":\"" + IntegratorKey + "\"}";
apiClient.addDefaultHeader("X-DocuSign-Authentication", creds);
// assign api client to the Configuration object
Configuration.setDefaultApiClient(apiClient);
// create an empty list that we will populate with accounts
List<LoginAccount> loginAccounts = null;
try
{
// login call available off the AuthenticationApi
AuthenticationApi authApi = new AuthenticationApi();
// login has some optional parameters we can set
AuthenticationApi.LoginOptions loginOps = authApi.new LoginOptions();
loginOps.setApiPassword("true");
loginOps.setIncludeAccountIdGuid("true");
LoginInformation loginInfo = authApi.login(loginOps);
// note that a given user may be a member of multiple accounts
loginAccounts = loginInfo.getLoginAccounts();
System.out.println("LoginInformation: " + loginAccounts);
}
catch (com.docusign.esign.client.ApiException ex)
{
System.out.println("Exception: " + ex);
}
// create a byte array that will hold our document bytes
byte[] fileBytes = null;
try
{
//String currentDir = System.getProperty("user.dir");
// read file from a local directory
//Path path = Paths.get(currentDir + SignTest1File);
Path path = Paths.get(SignTest1File);
fileBytes = Files.readAllBytes(path);
}
catch (IOException ioExcp)
{
// handle error
System.out.println("Exception: " + ioExcp);
return;
}
// create an envelope that will store the document(s), tabs(s), and recipient(s)
EnvelopeDefinition envDef = new EnvelopeDefinition();
envDef.setEmailSubject("[Java SDK] - Please sign this doc");
// add a document to the envelope
Document doc = new Document();
String base64Doc = Base64.getEncoder().encodeToString(fileBytes);
doc.setDocumentBase64(base64Doc);
doc.setName("TestFile.pdf"); // can be different from actual file name
doc.setDocumentId("1");
List<Document> docs = new ArrayList<Document>();
docs.add(doc);
envDef.setDocuments(docs);
// add a recipient to sign the document, identified by name and email we used above
Signer signer = new Signer();
signer.setName(recipientName);
signer.setEmail(recipientEmail);
signer.setRecipientId("1");
// to embed the recipient you must set their |clientUserId| property!
signer.setClientUserId("1234");
// create a signHere tab somewhere on the document for the signer to sign
// default unit of measurement is pixels, can be mms, cms, inches also
SignHere signHere = new SignHere();
signHere.setDocumentId("1");
signHere.setPageNumber("1");
signHere.setRecipientId("1");
signHere.setXPosition("100");
signHere.setYPosition("150");
// can have multiple tabs, so need to add to envelope as a single element list
List<SignHere> signHereTabs = new ArrayList<SignHere>();
signHereTabs.add(signHere);
Tabs tabs = new Tabs();
tabs.setSignHereTabs(signHereTabs);
signer.setTabs(tabs);
// add recipients (in this case a single signer) to the envelope
envDef.setRecipients(new Recipients());
envDef.getRecipients().setSigners(new ArrayList<Signer>());
envDef.getRecipients().getSigners().add(signer);
// send the envelope by setting |status| to "sent". To save as a draft set to "created"
envDef.setStatus("sent");
// accountId is needed to create the envelope and for requesting the signer view
String accountId = null;
String envelopeId = null;
try
{
// use the |accountId| we retrieved through the Login API to create the Envelope
accountId = loginAccounts.get(0).getAccountId();
// instantiate a new EnvelopesApi object
EnvelopesApi envelopesApi = new EnvelopesApi();
// call the createEnvelope() API to send the signature request!
EnvelopeSummary envelopeSummary = envelopesApi.createEnvelope(accountId, envDef);
// save the |envelopeId| that was generated and use in next API call
envelopeId = envelopeSummary.getEnvelopeId();
System.out.println("EnvelopeSummary: " + envelopeSummary);
}
catch (com.docusign.esign.client.ApiException ex)
{
System.out.println("Exception: " + ex);
}
// use the |accountId| we retrieved through the Login API and the |envelopeId| that was generated during envelope creation
accountId = loginAccounts.get(0).getAccountId();
// instantiate a new EnvelopesApi object
EnvelopesApi envelopesApi = new EnvelopesApi();
// set the url where you want the recipient to go once they are done signing
RecipientViewRequest returnUrl = new RecipientViewRequest();
returnUrl.setReturnUrl("https://www.docusign.com/devcenter");
returnUrl.setAuthenticationMethod("email");
// recipient information must match embedded recipient info we provided in step #2
returnUrl.setUserName(recipientName);
returnUrl.setEmail(recipientEmail);
returnUrl.setRecipientId("1");
returnUrl.setClientUserId("1234");
try
{
// call the CreateRecipientView API then navigate to the URL to start the signing session
ViewUrl recipientView = envelopesApi.createRecipientView(accountId, envelopeId, returnUrl);
System.out.println("ViewUrl: " + recipientView);
}
catch (com.docusign.esign.client.ApiException ex)
{
System.out.println("Exception: " + ex);
}

You are setting below attribute in your code, which is making this recipient an embedded signer. If you set clientUserId then you are telling DocuSign that treat this signer as embedded signer, and for embedded Signers DocuSign does not send any email for starting the signing ceremony. If you do not set clientUserId then DocuSign treats it as remote Signers and you will receive an email to start the Signing ceremony.
signer.setClientUserId("1234");
Code Example shows how to request an ESignature via an Email, and check Embedded Signing Example for embedded signing or Signing from Your App.

Related

Update user password with LDAP when the user has the flag 'User must change password at next logon' set, leads to error 49, subcode 773

When I try to change the password of a user via LDAP, in whose AD account the setting is set that the password must be changed at the next login, I get the following error:
cause: javax.naming.AuthenticationException: [LDAP: error code 49 - 80090308: LdapErr: DSID-0C090447, comment: AcceptSecurityContext error, data 773, v3839
Subcode 773 indicates that the user must reset the password, which is exactly what I intend to do right now.
With the following code I can successfully change the password if the above flag is not set:
public void updateUserPassword(String user, String oldPassword,
String newPassword) throws NamingException, LoginException {
try {
InitialDirContext ctx = this.getContext();
String filter = "(&(objectClass=user)(sAMAccountName=" + user + "))";
String baseDn = (String) this.getActiveDirectoryProps().get("baseDN_User");
// Search for user entry
SearchControls ctls = new SearchControls();
ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
ctls.setReturningObjFlag(true);
String[] returnAttrs = new String[3];
returnAttrs[0] = "cn"; // Common Name
returnAttrs[1] = "displayName";
returnAttrs[2] = "description";
NamingEnumeration<SearchResult> enumSearchResult = ctx.search(baseDn, filter, returnAttrs, ctls);
if (enumSearchResult.hasMore()) {
SearchResult result = enumSearchResult.next();
DirContext userCtx = (DirContext) result.getObject();
// Change the BindUser
ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, userCtx.getNameInNamespace());
ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, oldPassword);
// Update password
Attribute oldattr = new BasicAttribute("unicodePwd", toUnicodeBytes(oldPassword));
Attribute newattr = new BasicAttribute("unicodePwd", toUnicodeBytes(newPassword));
ModificationItem olditem = new ModificationItem(DirContext.REMOVE_ATTRIBUTE, oldattr);
ModificationItem newitem = new ModificationItem(DirContext.ADD_ATTRIBUTE, newattr);
String dn = userCtx.getNameInNamespace();
ctx.modifyAttributes(dn, new ModificationItem[]{olditem, newitem});
}
ctx.close();
} catch (final NamingException nE) {
//
} catch (Exception E) {
//
} finally {
//
}
}
So, do you have any idea what needs to be changed? Or what the reason is that it does not work?
My guess is that you just need to remove these lines:
// Change the BindUser
ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, userCtx.getNameInNamespace());
ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, oldPassword);
You can't authenticate with the old password since it's no longer valid. But you also don't need to bind with the user's own credentials when changing the password, since you have to provide the old password in the request.
These lines may give you trouble too:
Attribute oldattr = new BasicAttribute("unicodePwd", toUnicodeBytes(oldPassword));
Attribute newattr = new BasicAttribute("unicodePwd", toUnicodeBytes(newPassword));
The passwords do have to converted to unicode bytes, but they also have to be enclosed in double quotes too ("). So you'll probably have to add double quotes before passing it to toUnicodeBytes().
You can manage it in two steps:
In case "user must change password" it set, you should change the password of the user to an initial password as admin (bind).
Attribute oldattr = new BasicAttribute("unicodePwd", toUnicodeBytes(oldPassword));
Attribute newattr = new BasicAttribute("unicodePwd", toUnicodeBytes(initialPassword));
Then, after a bind with the user with the (initial) password the user (himself) should change his password.
Attribute oldattr = new BasicAttribute("unicodePwd", toUnicodeBytes(initialPassword)));
Attribute newattr = new BasicAttribute("unicodePwd", toUnicodeBytes(newPassword));
(with double quotes, if you like)
This can work also in case if the user's password is expired.

Connect to Wildfly Elytron's Credential Store with Masked Password

I have a credential store that I created with Elytron's tool giving a clear text password: "mypassword". In my Java program I can connect to the store with the following code;
Password storePassword = ClearPassword.createRaw(ClearPassword.ALGORITHM_CLEAR,"mypassword");
CredentialStore.ProtectionParameter protectionParameter = new CredentialStore.CredentialSourceProtectionParameter(
IdentityCredentials.NONE.withCredential(new PasswordCredential(storePassword)));
Provider provider = new WildFlyElytronPasswordProvider();
Security.addProvider(provider);
CredentialStore credentialStore = CredentialStore.getInstance(KeyStoreCredentialStore.KEY_STORE_CREDENTIAL_STORE);
// Configure and Initialise the CredentialStore
String configPath = System.getProperty("jboss.server.data.dir");
Map<String, String> configuration = new HashMap<>();
String path = configPath + File.separator + "credentials" + File.separator + "csstore.jceks";
configuration.put("keyStoreType", "JCEKS");
configuration.put("location", path);
configuration.put("modifiable", "false");
//Initialize credentialStore
credentialStore.initialize(configuration, protectionParameter);
However, I now want to connect to the credential store with an encrypted password instead of a clear text. For this purpose, I again used Elytron's tool to create a Masked Passowrd of "mypassword" with the following command;
elytron-tool.sh mask --salt 12345678 --iteration 123 --secret mypassword;
Here the values for salt and iteration are just random, could be anything. The above command gives me the masked password which is;
MASK-38PaKyS.9hHaRq7pAaE5tB;12345678;123
I now need a way to connect to credential store with this masked password within my Java program. I found that there is also a class called "MaskedPassword" which I might use but I couldn't find out how.
Any suggestions?
When you use elytron tool to generate masked password then you get string with prefix MASK- and suffix with salt and iteration
in your case - MASK-38PaKyS.9hHaRq7pAaE5tB;12345678;123
you can use below piece of code to decrypt the masked password,
private char[] getUnmaskedPass(String maskedPassword) throws GeneralSecurityException {
int maskLength = enter code here"MASK-".length();
if (maskedPassword == null || maskedPassword.length() <= maskLength) {
throw new GeneralSecurityException();
}
String[] parsed = maskedPassword.substring(maskLength).split(";");
if (parsed.length != 3) {
throw new GeneralSecurityException();
}
String encoded = parsed[0];
String salt = parsed[1];
int iteration = Integer.parseInt(parsed[2]);
PasswordBasedEncryptionUtil encryptUtil = new PasswordBasedEncryptionUtil.Builder().picketBoxCompatibility().salt(salt).iteration(iteration)
.decryptMode().build();
return encryptUtil.decodeAndDecrypt(encoded);
}
Now you can use this in your piece of code as a clearPassword. I hope that helped.
Source - https://github.com/wildfly-security/wildfly-elytron-tool/blob/master/src/main/java/org/wildfly/security/tool/MaskCommand.java static char[] decryptMasked(String maskedPassword)
We can create it using the below code...
Password storePassword = MaskedPassword.createRaw(MaskedPassword.ALGORITHM_MASKED_MD5_DES, <CREDENTIAL_STORE_ENTRY_PREFIX>.toCharArray(), 120,"12345678".getBytes(StandardCharsets.UTF_8),"MASK-38PaKyS.9hHaRq7pAaE5tB".getBytes(StandardCharsets.UTF_8));
....
....

Error using DocuSign AuthenticationApi.login() for Legacy Authentication - Missing grant_type/code

I'm trying to use the Authentication::login() API call in the DocuSign Java SDK and am receiving an error. Here's some code:
#Component
public class TestClass {
private ApiClient apiClient;
public void authenticate() {
this.apiClient = new ApiClient("account-d.docusign.com", "docusignAccessCode",
"mySecretIntegratorKey", "myClientSecret");
final AuthenticationApi authenticationApi = new AuthenticationApi(this.apiClient);
try {
// ERROR ON THE LINE BELOW
final LoginInformation loginInformation = authenticationApi.login();
} catch (final ApiException e) {
// do something appropriate
}
}
}
The mySecretIntegratorKey and myClientSecret values are not the real values I'm sending in obviously, but the other ones are.
Here is the error I am receiving when making the login() call:
Caused by: org.apache.oltu.oauth2.common.exception.OAuthSystemException: Missing grant_type/code
at com.docusign.esign.client.auth.OAuth$OAuthJerseyClient.execute(OAuth.java:184)
at org.apache.oltu.oauth2.client.OAuthClient.accessToken(OAuthClient.java:65)
at org.apache.oltu.oauth2.client.OAuthClient.accessToken(OAuthClient.java:55)
at org.apache.oltu.oauth2.client.OAuthClient.accessToken(OAuthClient.java:71)
at com.docusign.esign.client.auth.OAuth.updateAccessToken(OAuth.java:92)
... 123 common frames omitted
I realize that this is using the older legacy authentication, however I have a limitation that won't allow me to upgrade to the newer method of authentication until the first of the year. So for now I need to use this legacy method using SDK Version 2.2.1.
Any ideas what I'm doing wrong here? I'm sure it is something simple...
Thank you for your time.
You want to use Legacy authentication?
In that case you need to make a number of updates to your code.
Only call new ApiClient(base_url)
Set the X-DocuSign-Authentication header--
From an old Readme:
String authHeader = "{\"Username\":\"" + username +
"\",\"Password\":\"" + password +
"\",\"IntegratorKey\":\"" + integratorKey + "\"}";
apiClient.addDefaultHeader("X-DocuSign-Authentication", authHeader);
Then use the authenticationApi.login to look up the user's Account ID(s) and matching base urls.
The authenticationApi.login doe not actually log you in. (!)
Rather, that method just gives you information about the current user.
There is no login with the API since it does not use sessions. Instead, credentials are passed with every API call. The credentials can be an Access Token (preferred), or via Legacy Authentication, a name / password / integration key triplet.
When using Legacy Authentication, the client secret is not used.
More information: see the Readme section for using username/password in this old version of the repo.
Just in case someone was looking for complete legacy code that works! The below C# code snippet works. This is production ready code. I've tested it and it works. You will have to create an EnvelopeDefinition separately as this code is not included. However, the piece below will authenticate the user and will successfully send an envelope and get back the Envelope ID:
string username = "john.bunce#mail.com";
string password = "your_password";
string integratorKey = "your_integration_key";
ApiClient apiClient = new ApiClient("https://www.docusign.net/restapi");
string authHeader = "{\"Username\":\"" + username + "\", \"Password\":\"" + password + "\", \"IntegratorKey\":\"" + integratorKey + "\"}";
apiClient.Configuration.AddDefaultHeader("X-DocuSign-Authentication", authHeader);
AuthenticationApi authApi = new AuthenticationApi(apiClient.Configuration);
LoginInformation loginInfo = authApi.Login();
string accountId = loginInfo.LoginAccounts[0].AccountId;
string baseURL = loginInfo.LoginAccounts[0].BaseUrl;
string[] baseUrlArray= Regex.Split(baseURL, "/v2");
ApiClient apiClient2 = new ApiClient(baseUrlArray[0]);
string authHeader2 = "{\"Username\":\"" + username + "\", \"Password\":\"" + password + "\", \"IntegratorKey\":\"" + integratorKey + "\"}";
apiClient2.Configuration.AddDefaultHeader("X-DocuSign-Authentication", authHeader2);
EnvelopesApi envelopesApi = new EnvelopesApi(apiClient2.Configuration);
EnvelopeSummary results = envelopesApi.CreateEnvelope(accountId, envelopeDefinition);
string envelopeID = results.EnvelopeId;

Add embedded image in emails in AWS SES service

I am trying to write a Java app which can send emails to specify emails. In the email i also want to attach some pic.
Please find my code below :-
public class AmazonSESSample {
static final String FROM = "abc#gmail.com";
static final String TO = "def#gmail.com";
static final String BODY = "This email was sent through Amazon SES by using the AWS SDK for Java. hello";
static final String SUBJECT = "Amazon SES test (AWS SDK for Java)";
public static void main(String[] args) throws IOException {
Destination destination = new Destination().withToAddresses(new String[] { TO });
Content subject = new Content().withData(SUBJECT);
Message msg = new Message().withSubject(subject);
// Include a body in both text and HTML formats
//Content textContent = new Content().withData("Hello - I hope you're having a good day.");
Content htmlContent = new Content().withData("<h2>Hi User,</h2>\n"
+ " <h3>Please find the ABC Association login details below</h3>\n"
+ " <img src=\"logo.png\" alt=\"Mountain View\">\n"
+ " Click here to go to the association portal.\n"
+ " <h4>Association ID - 12345</h4>\n" + " <h4>Admin UID - suny342</h4>\n"
+ " <h4>Password - poass234</h4>\n" + " Regards,\n" + " <br>Qme Admin</br>");
Body body = new Body().withHtml(htmlContent);
msg.setBody(body);
SendEmailRequest request = new SendEmailRequest().withSource(FROM).withDestination(destination)
.withMessage(msg);
try {
System.out.println("Attempting to send an email through Amazon SES by using the AWS SDK for Java...");
AWSCredentials credentials = null;
credentials = new BasicAWSCredentials("ABC", "CDF");
try {
// credentialsProvider.
} catch (Exception e) {
throw new AmazonClientException("Cannot load the credentials from the credential profiles file. "
+ "Please make sure that your credentials file is at the correct "
+ "location (/Users/iftekharahmedkhan/.aws/credentials), and is in valid format.", e);
}
AmazonSimpleEmailService client = AmazonSimpleEmailServiceClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(credentials)).withRegion("us-west-2").build();
client.sendEmail(request);
System.out.println("Email sent!");
} catch (Exception ex) {
System.out.println("The email was not sent.");
System.out.println("Error message: " + ex.getMessage());
}
}
}
The image is placed in the resource directory but it is not being embeded in the email. Can anyone please help.
Instead of relative path, you'll need to use either an absolute public path to the image itself or a data URL. For example:
<img src=\"https://example.com/logo.png\" alt=\"Mountain View\" />
or
<img src=\"data:image/png;base64, {BASE64_ENCODED_DATA}\" alt=\"Mountain View\" />
EDIT
As of January 2020, Gmail still does not support base64 encoded images.
The method posted by #sebagra works well.
In case of Python using boto3 and ses client, the way to set to set the Content-Disposition to inline is:
att.add_header('Content-ID', '<myImage>')
att.add_header('Content-Disposition', 'inline', filename=os.path.basename(IMAGE_PATH))
Full example based on the python example in the AWS docs:
import os
import boto3
from botocore.exceptions import ClientError
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
# Replace sender#example.com with your "From" address.
# This address must be verified with Amazon SES.
SENDER = "Sender Name <sender#example.com>"
# Replace recipient#example.com with a "To" address. If your account
# is still in the sandbox, this address must be verified.
RECIPIENT = "recipient#example.com"
# Specify a configuration set. If you do not want to use a configuration
# set, comment the following variable, and the
# ConfigurationSetName=CONFIGURATION_SET argument below.
CONFIGURATION_SET = "ConfigSet"
# If necessary, replace us-west-2 with the AWS Region you're using for Amazon SES.
AWS_REGION = "us-west-2"
# The subject line for the email.
SUBJECT = "Customer service contact info"
# The full path to the file that will be attached to the email.
IMAGE_PATH = "path/to/myImage.png"
# The email body for recipients with non-HTML email clients.
BODY_TEXT = "Hello,\r\nPlease see the attached file for a list of customers to contact."
# The HTML body of the email.
BODY_HTML = """\
<html>
<head></head>
<body>
<h1>Hello!</h1>
<p>Please see the attached file for a list of customers to contact.</p>
</body>
</html>
"""
# The character encoding for the email.
CHARSET = "utf-8"
# Create a new SES resource and specify a region.
client = boto3.client('ses',region_name=AWS_REGION)
# Create a multipart/mixed parent container.
msg = MIMEMultipart('mixed')
# Add subject, from and to lines.
msg['Subject'] = SUBJECT
msg['From'] = SENDER
msg['To'] = RECIPIENT
# Create a multipart/alternative child container.
msg_body = MIMEMultipart('alternative')
# Encode the text and HTML content and set the character encoding. This step is
# necessary if you're sending a message with characters outside the ASCII range.
textpart = MIMEText(BODY_TEXT.encode(CHARSET), 'plain', CHARSET)
htmlpart = MIMEText(BODY_HTML.encode(CHARSET), 'html', CHARSET)
# Add the text and HTML parts to the child container.
msg_body.attach(textpart)
msg_body.attach(htmlpart)
# Define the attachment part and encode it using MIMEApplication.
att = MIMEApplication(open(IMAGE_PATH, 'rb').read())
# Add a header to tell the email client to treat this part as an attachment,
# and set an id and content disposition.
att.add_header('Content-ID', '<myImage>')
att.add_header('Content-Disposition', 'inline', filename=os.path.basename(IMAGE_PATH))
# Attach the multipart/alternative child container to the multipart/mixed
# parent container.
msg.attach(msg_body)
# Add the attachment to the parent container.
msg.attach(att)
try:
response = client.send_raw_email(
Source=SENDER,
Destinations=[
RECIPIENT
],
RawMessage={
'Data': msg.as_string(),
}
)
# Display an error if something goes wrong.
except ClientError as e:
print(e.response['Error']['Message'])
else:
print("Email sent! Message ID:"),
print(response['MessageId'])
In case of using sesv2 the msg is built the same but the the api to use is send_email:
...
client = boto3.client('sesv2',region_name=AWS_REGION)
...
response = client.send_email(
FromEmailAddress=SENDER,
Destination={
'ToAddresses': [
RECIPIENT
]
},
Content={
'Raw': {
'Data': msg.as_string()
}
}
)
...
I was able to send an email using AWS SES with images that can be seen in the GMail client, by attaching the images to the message and using an inline disposition reference to them.
I used the code explained in the AWS docs to attach images to a MimeMessage, and then using the cid reference from the HTML to those images (as explained in this post answer).
First, we attach the images to the message adding a couple of specific attributes (Header and Disposition):
MimeMultipart msg = new MimeMultipart("mixed");
DataSource fds = new FileDataSource("/path/to/my/image.png");
att.setDataHandler(new DataHandler(fds));
att.setFileName(fds.getName());
att.setHeader("Content-ID","<myImage>");
att.setDisposition("inline; filename=\"image.png\"");
msg.addBodyPart(att);
Note that the < and > in the Content-ID attribute must be present enclosing whatever id you choose (myImage in my example).
Then, in the HTML of the message body we just need to add the cid (content id) of each image:
<img src="cid:myImage">
For the full code, I pretty much used the AWS reference above (using same variable names), the only changes made were the ones of the setHeader and setDisposition methods.
I had no trouble sending an inline base 64 image to a Yahoo account using AWS SES. When I tried to send to a GMail account I had trouble. The text I sent rendered, but the image didn't show.
I discovered that GMail wasn't stripping the image. It was just not displaying it. I confirmed this by selecting More -> "Show original" while viewing the message in GMail.

Subject must match Issuer claim in the client assertion

I want to integrate office365 service management API for collecting events from it.I want to use client credential way to use service to service call but i am getting following error,
{
"error":"invalid_client",
"error_description":"AADSTS50048: Subject must match Issuer claim in the client assertion.
\r\nTrace ID: 1ad7acd8-3945-4fe0-a313-07638eb76e42\r\nCorrelation ID: a6c3a3c9-b737-4bfc-894f-3086c3ce8dfa\r\nTimestamp: 2016-06-09 07:20:15Z",
"error_codes":[50048
],
"timestamp":"2016-06-09 07:20:15Z",
"trace_id":"1ad7acd8-3945-4fe0-a313-07638eb76e42",
"correlation_id":"a6c3a3c9-b737-4bfc-894f-3086c3ce8dfa"
}
i use following doc to integration,
For getting client assersion,
https://msdn.microsoft.com/en-us/library/azure/dn645543.aspx I am getting this. But for Access token,
https://msdn.microsoft.com/en-us/library/office/dn707383.aspx I not getting this as a response getting above error.
Somebody help me please :)
How did you get the client_assertion? The link you provide doesn’t describe how to get the ‘client_assertion’. It acquire the token with the app’s id and secret which is doesn’t support for the Office 365 Management API. You can refer the blog to about the ‘client_assertion’.
And here is an C# code sample which use the ADAL to get the access token for the client credentials flow:
string clientId = "{clientId}";
string certThumbprint = "‎{copy from mmc}";
certThumbprint = certThumbprint.Replace("\u200e", string.Empty).Replace("\u200f", string.Empty).Replace(" ", string.Empty);
string apiResourceId = "https://manage.office.com";
X509Certificate2 cert = null;
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
string authority = "https://login.windows.net/{yourTentant}";
var authContext = new AuthenticationContext(authority);
try
{
store.Open(OpenFlags.ReadOnly);
cert = store.Certificates.Find(X509FindType.FindByThumbprint, certThumbprint, false)[0];
}
finally
{
store.Close();
}
var certCred = new ClientAssertionCertificate(clientId, cert);
AuthenticationResult result = null;
try
{
result = await authContext.AcquireTokenAsync(apiResourceId, certCred);
}
catch (Exception ex)
{
}

Categories