I am trying to send email with an excel attachment using AWS SES java SDK. I am following the code template provided by AWS. https://docs.aws.amazon.com/ses/latest/DeveloperGuide/examples-send-raw-using-sdk.html
But I am getting javax.mail.internet.ParseException. Any idea what's going on here ?
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Properties;
//JavaMail libraries. Download the JavaMail API
//from https://javaee.github.io/javamail/
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.util.ByteArrayDataSource;
import org.apache.log4j.Logger;
//AWS SDK libraries. Download the AWS SDK for Java
//from https://aws.amazon.com/sdk-for-java
import com.amazonaws.regions.Regions;
import com.amazonaws.services.simpleemail.AmazonSimpleEmailService;
import com.amazonaws.services.simpleemail.AmazonSimpleEmailServiceClientBuilder;
import com.amazonaws.services.simpleemail.model.RawMessage;
import com.amazonaws.services.simpleemail.model.SendRawEmailRequest;
public class AmazonSESSample {
private final Logger logger = Logger.getLogger(getClass());
// Replace [email protected] with your "From" address.
// This address must be verified with Amazon SES.
private static String SENDER = "US CWB INTDEV <[email protected]>";
// Replace [email protected] with a "To" address. If your account
// is still in the sandbox, this address must be verified.
private static String RECIPIENT = "[email protected]";
// 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.
private static String CONFIGURATION_SET = "ConfigSet";
// The subject line for the email.
private static String SUBJECT = "Weekly users and projects report";
// The email body for recipients with non-HTML email clients.
private static String BODY_TEXT = "Hello,\r\n" + "Please see the attached file for a list "
+ "of customers to contact.";
// The HTML body of the email.
private static String 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>";
public void send(byte[] attachment) throws AddressException, MessagingException, IOException {
Session session = Session.getDefaultInstance(new Properties());
// Create a new MimeMessage object.
MimeMessage message = new MimeMessage(session);
// Add subject, from and to lines.
message.setSubject(SUBJECT, "UTF-8");
message.setFrom(new InternetAddress(SENDER));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(RECIPIENT));
// Create a multipart/alternative child container.
MimeMultipart msg_body = new MimeMultipart("alternative");
// Create a wrapper for the HTML and text parts.
MimeBodyPart wrap = new MimeBodyPart();
// Define the text part.
MimeBodyPart textPart = new MimeBodyPart();
textPart.setContent(BODY_TEXT, "text/plain; charset=UTF-8");
// Define the HTML part.
MimeBodyPart htmlPart = new MimeBodyPart();
htmlPart.setContent(BODY_HTML, "text/html; charset=UTF-8");
// Add the text and HTML parts to the child container.
msg_body.addBodyPart(textPart);
msg_body.addBodyPart(htmlPart);
// Add the child container to the wrapper object.
wrap.setContent(msg_body);
// Create a multipart/mixed parent container.
MimeMultipart msg = new MimeMultipart("mixed");
// Add the parent container to the message.
message.setContent(msg);
// Add the multipart/alternative part to the message.
msg.addBodyPart(wrap);
// Define the attachment
MimeBodyPart att = new MimeBodyPart();
DataSource fds = new ByteArrayDataSource(attachment, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
att.setDataHandler(new DataHandler(fds));
att.setFileName(fds.getName());
// Add the attachment to the message.
msg.addBodyPart(att);
// Try to send the email.
try {
System.out.println("Attempting to send an email through Amazon SES " + "using the AWS SDK for Java...");
// Instantiate an Amazon SES client, which will make the service
// call with the supplied AWS credentials.
AmazonSimpleEmailService client = AmazonSimpleEmailServiceClientBuilder.standard()
// Replace US_WEST_2 with the AWS Region you're using for
// Amazon SES.
.withRegion(Regions.US_WEST_2).build();
// Print the raw email content on the console
// Send the email.
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
message.writeTo(outputStream);
RawMessage rawMessage = new RawMessage(ByteBuffer.wrap(outputStream.toByteArray()));
SendRawEmailRequest rawEmailRequest = new SendRawEmailRequest(rawMessage)
.withConfigurationSetName(CONFIGURATION_SET);
client.sendRawEmail(rawEmailRequest);
System.out.println("Email sent!");
// Display an error if something goes wrong.
} catch (Exception ex) {
System.out.println("Email Failed");
System.err.println("Error message: " + ex.getMessage());
ex.printStackTrace();
}
}
}
Here is the stack trace.
2019-01-10 09:57:52 <2a7abff3-14be-11e9-9b09-dbd922fa0afd> DEBUG AmazonWebServiceClient:79 - Internal logging successfully configured to commons logger: true
Email Failed
Error message: Expected parameter value, got "null"
javax.mail.internet.ParseException: Expected parameter value, got "null"
at javax.mail.internet.ParameterList.<init>(ParameterList.java:169)
at javax.mail.internet.ContentDisposition.<init>(ContentDisposition.java:87)
at javax.mail.internet.MimeBodyPart.updateHeaders(MimeBodyPart.java:1307)
at javax.mail.internet.MimeBodyPart.updateHeaders(MimeBodyPart.java:1001)
at javax.mail.internet.MimeMultipart.updateHeaders(MimeMultipart.java:333)
at javax.mail.internet.MimeBodyPart.updateHeaders(MimeBodyPart.java:1255)
at javax.mail.internet.MimeMessage.updateHeaders(MimeMessage.java:2012)
at javax.mail.internet.MimeMessage.saveChanges(MimeMessage.java:1980)
at javax.mail.internet.MimeMessage.writeTo(MimeMessage.java:1680)
at javax.mail.internet.MimeMessage.writeTo(MimeMessage.java:1659)
at com.acme.workbench.project.list.email.service.AmazonSESSample.send(AmazonSESSample.java:131)
at com.acme.workbench.project.list.email.service.ProjectListEmailService.execute(ProjectListEmailService.java:60)
at com.acme.lambda.handler.LambdaFunctionForScheduledEvent.execute(LambdaFunctionForScheduledEvent.java:68)
at com.acme.lambda.handler.LambdaFunctionForScheduledEvent.handleRequest(LambdaFunctionForScheduledEvent.java:55)
at com.acme.lambda.handler.LambdaFunctionForScheduledEvent.handleRequest(LambdaFunctionForScheduledEvent.java:13)
at lambdainternal.EventHandlerLoader$PojoHandlerAsStreamHandler.handleRequest(EventHandlerLoader.java:178)
at lambdainternal.EventHandlerLoader$2.call(EventHandlerLoader.java:888)
at lambdainternal.AWSLambda.startRuntime(AWSLambda.java:293)
at lambdainternal.AWSLambda.<clinit>(AWSLambda.java:64)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:348)
at lambdainternal.LambdaRTEntry.main(LambdaRTEntry.java:104)
You copied code that set the attachment from a file and changed it to set the attachment from a byte array, but the ByteArrayDataSource has no name so when you set the file name for the attachment you set it to null, which is what causes the problem. Change the call to att.setFileName to set a non-null file name.