I am currently using AWS SDK to send mails:
// from: noreply#domain.com
public void sendMail(String from, String to, String subject, String htmlBody) {
LOGGER.info(String.format("Sending Mail from: %s, to: %s, with subject: %s", from, to, subject));
try {
AWSCredentials credentials = new BasicAWSCredentials(awsAccessKey, awsSecret);
AmazonSimpleEmailService client = AmazonSimpleEmailServiceClientBuilder.standard()
.withRegion(Regions.AP_SOUTH_1).withCredentials(new AWSStaticCredentialsProvider(credentials))
.build();
SendEmailRequest request = new SendEmailRequest().withDestination(new Destination().withToAddresses(to))
.withMessage(new Message()
.withBody(new Body().withHtml(new Content().withCharset("UTF-8").withData(htmlBody)))
.withSubject(new Content().withCharset("UTF-8").withData(subject)))
.withSource(from);
client.sendEmail(request);
} catch (Exception e) {
LOGGER.error(String.format("Error while sending email: %s", e.getMessage()));
throw new IllegalArgumentException(MessageEnum.FAILED_TO_SEND_AN_EMAIL.name());
}
}
The method works fine but the email is sent as:
But I am expecting the email to be sent with the sender name so that it can be displayed like:
Does anyone have any idea on how to send an email including the sender name? Any help is appreciated.
If you check documentation of SendEmailRequest you can find out that it supports standard way to define friendly name in email:
source - The email address that is sending the email. This email address must be either individually verified with Amazon SES, or from a domain that has been verified with Amazon SES. For information about verifying identities, see the Amazon SES Developer Guide.
If you are sending on behalf of another user and have been permitted to do so by a sending authorization policy, then you must also specify the SourceArn parameter. For more information about sending authorization, see the Amazon SES Developer Guide.
Amazon SES does not support the SMTPUTF8 extension, as described in RFC6531. For this reason, the local part of a source email address (the part of the email address that precedes the # sign) may only contain 7-bit ASCII characters. If the domain part of an address (the part after the # sign) contains non-ASCII characters, they must be encoded using Punycode, as described in RFC3492. The sender name (also known as the friendly name) may contain non-ASCII characters. These characters must be encoded using MIME encoded-word syntax, as described in RFC 2047. MIME encoded-word syntax uses the following form: =?charset?encoding?encoded-text?= .
So that string should look like:
John Doe <johndoe#example.com>
InternetAddress can be used for this, but you need to pay attention on encoding restrictions that SendEmailRequest has for from argument
request.withSource((new InternetAddress("mail#example.com", "Your Name")).toString());
You are using an old Amazon Simple Email Service API (V1). For best practice, use the SES Java V2 API. V2 packages always start with software.amazon...
The Amazon SDK team strongly recommends moving from V1 to V2:
The AWS SDK for Java 2.x is a major rewrite of the version 1.x code base. It’s built on top of Java 8+ and adds several frequently requested features. These include support for non-blocking I/O and the ability to plug in a different HTTP implementation at run time.
You can set this information (sender name) by setting the SendEmailRequest object properly.
Here is the Java V2 SES example.
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.ses.SesClient;
import software.amazon.awssdk.services.ses.model.*;
import software.amazon.awssdk.services.ses.model.Message;
import software.amazon.awssdk.services.ses.model.Body;
import javax.mail.MessagingException;
public class SendMessageEmailRequest {
public static void main(String[] args) {
final String USAGE = "\n" +
"Usage:\n" +
" <sender> <recipient> <subject> \n\n" +
"Where:\n" +
" sender - an email address that represents the sender. \n"+
" recipient - an email address that represents the recipient. \n"+
" subject - the subject line. \n" ;
if (args.length != 3) {
System.out.println(USAGE);
System.exit(1);
}
String sender = "foo#testmail.com" ;//args[0];
String recipient = "foo#testmail.com" ;//args[1];
String subject = "Test Email"; //args[2];
Region region = Region.US_EAST_1;
SesClient client = SesClient.builder()
.region(region)
.build();
// The email body for non-HTML email clients
String bodyText = "Hello,\r\n" + "See the list of customers. ";
// The HTML body of the email
String bodyHTML = "<html>" + "<head></head>" + "<body>" + "<h1>Hello!</h1>"
+ "<p> See the list of customers.</p>" + "</body>" + "</html>";
try {
send(client, sender, recipient, subject, bodyText, bodyHTML);
client.close();
System.out.println("Done");
} catch (MessagingException e) {
e.getStackTrace();
}
}
public static void send(SesClient client,
String sender,
String recipient,
String subject,
String bodyText,
String bodyHTML
) throws MessagingException {
Destination destination = Destination.builder()
.toAddresses(recipient)
.build();
Content content = Content.builder()
.data(bodyHTML)
.build();
Content sub = Content.builder()
.data(subject)
.build();
Body body = Body.builder()
.html(content)
.build();
Message msg = Message.builder()
.subject(sub)
.body(body)
.build();
SendEmailRequest emailRequest = SendEmailRequest.builder()
.destination(destination)
.message(msg)
.source(sender)
.build();
try {
System.out.println("Attempting to send an email through Amazon SES " + "using the AWS SDK for Java...");
client.sendEmail(emailRequest);
} catch (SesException e) {
System.err.println(e.awsErrorDetails().errorMessage());
System.exit(1);
}
}
}
Related
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;
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.
I have created a system with 4 main applications:
the identity server (C#)
the web app (angular, TS, JS)
the server side application (Java)
the API (C#)
The web app authenticates fine, the tokens work like a treat and allow access to the API, but the server-side app doesn't. The tokens seem to be generated correctly but when they are added to the request headers and dispatched they just return a 401 error.
If I generate the token through postman they work correctly but when I generate them through the java application they don't work. Also, they seem to be a different length.
The java application uses the client credentials flow to get token and is implemented like this:
String strBody;
try {
strBody = "client_id=" + id + "&client_secret=" + URLEncoder.encode(secret, "UTF-8") + "&grant_type=client_credentials&scope=" + scope;
} catch (UnsupportedEncodingException e) {
Logger.severe("Failed to get encode client secret with error: " + e.getMessage());
((CompletableFuture)accessToken).completeExceptionally(new Exception("Failed to get encode client secret with error: " + e.getMessage()));
return null;
}
RequestBody body = RequestBody.create(MediaType.parse("application/x-www-form-urlencoded; charset=utf-8"), strBody);
Request request = new Request.Builder().url(url).post(body).build();
String strResponse = executeRequest(request);
Logger.info("got token response: "+strResponse);
TokenResponse response = (new Gson()).fromJson(strResponse, TokenResponse.class);
if (response.getError() != null && response.getError().length() > 0) {
Logger.severe("Failed to get access token with error: " + response.getError());
((CompletableFuture)accessToken).completeExceptionally(new Exception("Failed to get access token with error: " + response.getError()));
} else {
Timers.runIn((timer, thing) -> clientCreditentalFlow(), response.getExpiresIn() - 10, TimeUnit.SECONDS);
Logger.info("token: "+accessToken);
((CompletableFuture)accessToken).complete(response.getAccessToken());
}
When I send the exact same details from post man, it returns a working token, although of a different length.
The web application uses the implicit work flow as opposes to the java app that uses the client credentials flow.
I'm sending a mail using JavaMail from inside a JSP page as follows:
String from= request.getParameter("from");
String to= request.getParameter("to");
String thanks= request.getParameter("thanks");
String subject= request.getParameter("subject");
try{
SmtpClient client = new SmtpClient("smtp.example.com");
client.from(from);
client.to(to);
PrintStream message = client.startMessage();
message.println("From: " + from);
message.println("To: " + to);
message.println("Subject: " + subject);
message.println();
Enumeration paramNames = request.getParameterNames();
while(paramNames.hasMoreElements()) {
String paramName = (String) paramNames.nextElement();
String paramValue = request.getParameter(paramName);
if (request.getParameter(paramName) != null &&
request.getParameter(paramName) != "") {
message.println(paramName + ": " + paramValue);
message.println();
}
}
client.closeServer();
}
catch (IOException e){
System.out.println("ERROR IN DELIVERING THE FORM:"+e);
}
This was working fine first and sent the data to my Inbox, but after many trials and insignificant changes, now the post goes to my Spam folder.
I appreciate if anyone could tell me where the problem is and what causes this.
Mail goes to spam when Google find any insecure IP or links, Make sure you don't have any other IP which is not authenticated (can be access by https://"IP")
What causes this? Your spam filter!
Depending on what you/your mail provider uses as spam filter, you might learn something from the mail headers - I recall spamassassin giving some information about what filter scored how high, and the resulting spam score. Others might do that as well.
You might also be able to train your spam filter to recognize this mail as non-spam (ham) if you remove it from the spamfolder.
If there is overflow emailId then most of the times it goes to spam, It's done by google. But you can still change that protocol by google by below method:
First time you need to go to your spam and open the mail then the cross option would be above the mail (Which means cancel that mail from spam) click on that (mentioned in the screenshot:.
From the next time, it would not go to your spam.
I have a requirement where I need to send SMS from my Web Application to any Mobile in India .
I got below code from a ipipi.com website:
I want to implement this functionality, could anybody please help me what values are to be provided here:
String username = "YoureIPIPIUsername";
String password = "YourPassword";
String smtphost = "ipipi.com";
String compression = "Compression Option goes here - find out more";
String from = "YoureIPIPIUsername#ipipi.com";
String to = "DestinationPhoneNumber#sms.ipipi.com";
String body = "Your Message";
SMTPSend.class
import java.io.*;
import java.net.InetAddress;
import java.util.Properties;
import java.util.Date;
import javax.mail.*;
import javax.mail.internet.*;
import javax.activation.*;
public class SMTPSend {
public SMTPSend() {
}
public void msgsend() {
String username = "YoureIPIPIUsername";
String password = "YourPassword";
String smtphost = "ipipi.com";
String compression = "Compression Option goes here - find out more";
String from = "YoureIPIPIUsername#ipipi.com";
String to = "DestinationPhoneNumber#sms.ipipi.com";
String body = "Your Message";
Transport tr = null;
try {
Properties props = System.getProperties();
props.put("mail.smtp.auth", "true");
// Get a Session object
Session mailSession = Session.getDefaultInstance(props, null);
// construct the message
Message msg = new MimeMessage(mailSession);
//Set message attributes
msg.setFrom(new InternetAddress(from));
InternetAddress[] address = {new InternetAddress(to)};
msg.setRecipients(Message.RecipientType.TO, address);
msg.setSubject(compression);
msg.setText(body);
msg.setSentDate(new Date());
tr = mailSession.getTransport("smtp");
tr.connect(smtphost, username, password);
msg.saveChanges();
tr.sendMessage(msg, msg.getAllRecipients());
tr.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] argv) {
SMTPSend smtpSend = new SMTPSend();
smtpSend.msgsend();
}
}
If the code above is linking to a service that converts incoming Email messages to outgoing SMS messages, you presumably need to purchase credit as stated by Alex K.
A better way to send SMSes would be to use SMSLib to interface with a cellular provider's SMSC. You also then need to make sure that provider is able to route SMSes to all cellular networks.
Your question seems specific to some service provider/API. But I would like to give a generic answer here.
Sending SMS need a SMS gateway to a SMSC. There are two simple methods[of-cause more can be].
You can either use your SIM card[SMS enabled], or use someone else's SIM card. SIM card provides connection to a SMS gateway through your service provider with SMSC.
Either ways, sending SMS is not free.Others may say its LIKELY free, but at-least an advertisement or a long term business marketing strategy must be there.
The way you are continuing is using someone else's SIM through an API provided by them. Since those have dedicated bulk SMS accounts, it may faster, multiple threaded, service. They should commercially helpful to you to get your problem sorted.
If you want to send SMS from your SIM, you have to connect your SIM to computer and use an standard API to call SMS functionality. SMSLib is what I suggest. You need a hardware to connect your SIM to PC, either connect your mobile to it or, use a Data Modem[easy] and interface through a COM port.
Try this code here, if you want to try your own SMS gateway.
First create an account in ipipi.com and validate it by clicking the activation link sent to the mail.And give your username as YoureIPIPIUsername and password as YourPassword.
String smtphost = "ipipi.com"
String compression = "Compression Option goes here - find out more";
There are some compression types here if u don't want anything you can mention "None"
String from = "YoureIPIPIUsername#ipipi.com"
String to = "DestinationPhoneNumber#sms.ipipi.com";
Destination ph number should be +91 and the 10 digit number
String body = "Your Message";