Amazon SES custom header List-Unsubscribe isn't working - java

I'm tryin to add the "List-Unsubscribe" header in my sent emails (through amazon ses) but when i see the received email there's no such header in it. I need it to reduce the number of spam complaints and to improve deliverability and reputation.
SendEmailRequest sendEmailRequest = new SendEmailRequest();
sendEmailRequest.putCustomRequestHeader(UNSUBSCRIBE_HEADER, unsuscribeURL);
PS: Using others providers such as Mandrill or Sendgrid it works, but i really need it at amazon

So... i found a workaround.
If you want to add a custom header to your message, always use a RawMessage, not a simple one.
Something like this:
SendRawEmailRequest sendRawEmailRequest = new SendRawEmailRequest();
RawMessage rawMessage = null;
rawMessage = buildSimpleRawMessage(...);
sendRawEmailRequest.setRawMessage(rawMessage);
private RawMessage buildSimpleRawMessage(String subject, String message, Attachment attachment) {
RawMessage rawMessage = null;
try {
// JavaMail representation of the message
Session s = Session.getInstance(new Properties(), null);
MimeMessage mimeMessage = new MimeMessage(s);
// Subject
mimeMessage.setSubject(subject);
// Add a MIME part to the message
MimeMultipart mimeBodyPart = new MimeMultipart();
BodyPart part = new MimeBodyPart();
part.setContent(message, "text/html");
mimeBodyPart.addBodyPart(part);
// Add a attachement to the message
if(attachment!=null){
part = new MimeBodyPart();
DataSource source = null;
source = new ByteArrayDataSource(attachment.getBuf(), attachment.getMimeType());
part.setDataHandler(new DataHandler(source));
part.setFileName(attachment.getFileName());
mimeBodyPart.addBodyPart(part);
}
mimeMessage.setContent(mimeBodyPart);
mimeMessage.addHeader(UNSUBSCRIBE_HEADER, unsubscribeURL);
// Create Raw message
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
mimeMessage.writeTo(outputStream);
rawMessage = new RawMessage(ByteBuffer.wrap(outputStream.toByteArray()));
} catch (Exception e) {
logger.error("There was a problem creating mail attachment", e);
throw Throwables.propagate(e);
}
return rawMessage;
}

Related

Spring Boot API - Send email with attachment from URL

This is what I have so far. I think I need a line like: helper.addAttachment(attachment); in there, but that doesn't compile. I just can't figure out the syntax of how to add this attachment. Anyone have any tips? Thanks!
#RequestMapping(value = "/api/sendemailsubmitted")
public void sendEmailSubmitted(#RequestBody VerifyInfo newVerifyInfo) throws MessagingException, MalformedURLException {
MimeMessage message = sender.createMimeMessage();
String username = newVerifyInfo.getUsername();
// Enable the multipart flag!
MimeMessageHelper helper = new MimeMessageHelper(message, true);
Part attachment = new MimeBodyPart();
URL url = new URL("https://www.url.com/applicationsubmitted.pdf");
attachment.setDataHandler(new DataHandler(url));
attachment.setDisposition(Part.ATTACHMENT);
attachment.setFileName(url.getFile());
helper.setTo(username);
helper.setFrom("AdmissionsApplication#gmail.com");
helper.setText("<html><body>" +
"Please see attachment" +
"</body></html>", true);
helper.setSubject("Begin Your Journey!");
sender.send(message);
}
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/mail/javamail/MimeMessageHelper.html
As you can see here you can just do a message.addAttachment("myDocument.pdf", new ClassPathResource("doc/myDocument.pdf"));
No need to create MimeBodyPart MimeBodyPart is used to add it to javax.mail.internet.MimeMultipart and then add it to javax.mail.internet.MimeMessage, however, you are using Spring with org.springframework.mail.javamail.MimeMessageHelper

Send attached in mail java

Here in this it works perfectly fine but instead of using the recieved file I have use file path
How can I do that
I though converting it into input stream would do some good but there is no constructor with input stream
Please let me know
Thanks in advance
#RequestMapping("/SendMail")
public String mail(#RequestParam("prescription") MultipartFile prescription,#RequestParam("email") String email,HttpSession session) {
try {
customer ct=custServ.customerExists(email);
InputStream in = prescription.getInputStream();
String filename=prescription.getName();
if(ct!=null){
final String SEmail="email#gmail.com";
final String SPass="passowrd";
final String REmail=email;
final String Sub="Your prescription is here!";
//mail send Code
Properties props=new Properties();
props.put("mail.smtp.host","smtp.gmail.com");
props.put("mail.smtp.socketFactory.port","465");
props.put("mail.smtp.socketFactory.class","javax.net.ssl.SSLSocketFactory");
props.put("mail.smtp.auth","true");
props.put("mail.smtp.port","465");
Session ses=Session.getInstance(props,
new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication(){
return new PasswordAuthentication(SEmail,SPass);
}
}
);
Message message=new MimeMessage(ses);
message.setFrom(new InternetAddress(SEmail));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(REmail));
message.setSubject(Sub);
BodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setText("This is your prescription here");
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(messageBodyPart);
messageBodyPart = new MimeBodyPart();
// File filep=new File(prescription);
DataSource source = new FileDataSource("C:\\Users\\Narci\\Desktop\\frontend\\Myqr3.jpg");
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName(filename);
multipart.addBodyPart(messageBodyPart);
message.setContent(multipart);
Transport.send(message);
session.setAttribute("msg","Mail Sent successfully.");
}
else{
session.setAttribute("msg", "Wrong Emial ID");
}
return "Doctor";
}
catch(Exception e) {
e.printStackTrace();
return "Error";
}
} ```
This is kind of a shot in the dark because I don't believe I truly understand the question. If the question is; How can I use a File instead of a MultipartFile and obtain an InputStream then the answer would be to use an existing library like Files.newInputStream with a Path as the parameter.
Path path = Paths.get("path", "to", "my", "file");
try (InputStream input = Files.newInputStream(path)) {
}
From this other Stack Overflow answer (this answer is posted as a community wiki) you can get in your front-end the file object and convert it into a base64 object as follows:
const toBase64 = file => new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = error => reject(error);
});
async function Main() {
const file = document.querySelector('#myfile').files[0];
console.log(await toBase64(file));
}
Main();
Then, with this Base64 object you could send it to the backend with a PUT request to then attach it to the email following Gmail API instructions for multipart upload.

email sending with multiple attachments using MultipartFile

I am using MultipartFile to send an email with multiple attachments. my code is working fine but I am storing each file in my project then I am attaching. I don't want to store that file anywhere instead I want the file directly send to the recipients.
My code is,
Controller:
#RequestMapping(value="/sendEmailAttachment",method=RequestMethod.POST)
public #ResponseBody Response sendEmail(#RequestParam("file") MultipartFile[] file,#ModelAttribute Email email) {
SendEmail mail = new SendEmail();
return mail.sendEmail(email,file);
}
Service:
public Response sendEmail(Email email,MultipartFile[] attachFiles) {
username = email.getUsername();
password = email.getPassword();
switch (email.getDomain()) {
case "1and1.com":
host = "smtp.1and1.com";
break;
case "gmail.com":
host = "smtp.gmail.com";
break;
case "yahoo.com":
host = "smtp.mail.yahoo.com";
break;
case "rediffmail.com":
host = "smtp.rediffmail.com";
break;
default:
host = "smtp.1and1.com";
username="support#gmail.com";
password="************";
break;
}
props.put("mail.smtp.host", host);
Response response = new Response();
Session session = Session.getInstance(props,
new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
try {
// Create a default MimeMessage object.
Message message = new MimeMessage(session);
InternetAddress[] myToList = InternetAddress.parse(email.getTo());
InternetAddress[] myBccList = InternetAddress.parse(email.getBcc());
InternetAddress[] myCcList = InternetAddress.parse(email.getCc());
// Set From: header field of the header.
message.setFrom(new InternetAddress(email.getUsername()));
// Set To: header field of the header.
message.setRecipients(Message.RecipientType.TO,myToList);
message.setRecipients(Message.RecipientType.BCC, myBccList);
message.setRecipients(Message.RecipientType.CC, myCcList);
// Set Subject: header field
message.setSubject(email.getSubject());
// Create the message part
BodyPart messageBodyPart = new MimeBodyPart();
// Now set the actual message
messageBodyPart.setContent(email.getBody(), "text/html");
// Create a multipar message
Multipart multipart = new MimeMultipart();
// Set text message part
multipart.addBodyPart(messageBodyPart);
if(attachFiles != null && attachFiles.length > 0){
for (MultipartFile filePath : attachFiles) {
MimeBodyPart attachPart = new MimeBodyPart();
try {
filePath.transferTo(new File(filePath.getOriginalFilename()).getAbsoluteFile());
attachPart.attachFile(filePath.getOriginalFilename());
} catch (IOException ex) {
ex.printStackTrace();
}
multipart.addBodyPart(attachPart);
}
}
// Send the complete message parts
message.setContent(multipart);
// Transport.send(message, message.getAllRecipients());
Transport.send(message);
response.setStatus(200);
response.setMessage("Sent Email Successfully");
} catch (MessagingException e) {
response.setStatus(-1);
response.setMessage(""+e);
response.setObject(e);
e.printStackTrace();
}
return response;
}
Here I have witten like,
filePath.transferTo(new File(filePath.getOriginalFilename()).getAbsoluteFile());
attachPart.attachFile(filePath.getOriginalFilename());
I dont want to transfer/save file into the project and attach, I want to send the file directly. any help will appreciated.
Try this:
attachPart.setContent(filePath.getBytes(), filePath.getContentType());
attachPart.setFileName(filePath.getOriginalFilename());
attachPart.setDisposition(Part.ATTACHMENT);
In my case, the answer of #Bill Shannon give me the error "java.io.IOException: “text/plain” DataContentHandler requires String object, was given object of type class [B"
I modified the code like this :
DataSource ds = new ByteArrayDataSource(filePath.getBytes(), filePath.getContentType());
attachPart.setDataHandler(new DataHandler(ds));
attachPart.setFileName(filePath.getOriginalFilename());
attachPart.setDisposition(Part.ATTACHMENT);
If you are using Spring, then you can use JavaMailSenderImpl and MimeMessageHelper:
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
MimeMessage mailMessage = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mailMessage, true);
helper.addAttachment("fileName", filePath);
mailSender.send(mailMessage);
List<MultipartFile> attachments = /* this will be input for multiple files */
Multipart multipart = new MimeMultipart();
MimeBodyPart mimeBodyPart = new MimeBodyPart();
mimeBodyPart.setContent(/* email content */, "text/html");
multipart.addBodyPart(mimeBodyPart);
for(int i = 0 ; i < attachments.size() ; i++) {
mimeBodyPart = new MimeBodyPart();
DataSource source = new ByteArrayDataSource(attachments.get(i).getBytes(), attachments.get(i).getContentType());
mimeBodyPart.setDataHandler(new DataHandler(source));
mimeBodyPart.setFileName(attachments.get(i).getOriginalFilename());
multipart.addBodyPart(mimeBodyPart);
}
email.setContent(multipart);

Javamail doesn't send email with larger attachments

I want to send an email using Javamail with 2 attachments. One of them is a json file, and the other one is a txt file (logcat.txt). The logcat.txt is about 1mb in size.
It doesn't send any email if I have the addAttachment(multipart,reportPath,"logcat.txt"); in my code. If I remove addAttachment(multipart,reportPath,"logcat.txt"); it works.
When the json file gets larger, at one point about 500kb, it doesn't send either.
My code:
public synchronized void sendReport(String subject, String body, String filepath, String filename, String reportPath, String sender, String recipients){
try {
Multipart multipart = new MimeMultipart("mixed"); //try adding "mixed" here as well but it doesn't work
MimeMessage message = new MimeMessage(session);
message.setSender(new InternetAddress(sender));
message.setSubject(subject);
//body
BodyPart messageBodyPart2 = new MimeBodyPart();
messageBodyPart2.setText(body);
Log.d(TAG, "sendReport: " + reportPath);
//this prints sendReport: /storage/emulated/0/Android/data/**app package name**/files/LOG-1472631395.json
Log.d(TAG, "sendReport: " + filepath);
//sendReport: /storage/emulated/0/Android/data/**app package name**/files/logcat.txt
addAttachment(multipart,filepath,filename);
addAttachment(multipart,reportPath,"logcat.txt");
multipart.addBodyPart(messageBodyPart2);
message.setContent(multipart);
if (recipients.indexOf(',') > 0)
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(recipients));
else
message.setRecipient(Message.RecipientType.TO, new InternetAddress(recipients));
Transport.send(message);
} catch (Exception e) {
e.printStackTrace();
}
}
private static void addAttachment(Multipart multipart, String filepath, String filename) throws MessagingException
{
DataSource source = new FileDataSource(filepath);
BodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName(filename);
multipart.addBodyPart(messageBodyPart);
}
I also use another method to send attachments but it doesn't work either:
private static void addAttachment(Multipart multipart, String filepath, String filename) throws Exception
{
MimeBodyPart mimeBodyPart = new MimeBodyPart();
mimeBodyPart.attachFile(filepath);
mimeBodyPart.setFileName(filename);
multipart.addBodyPart(mimeBodyPart);
}
Does anyone have an idea how to fix this? Thank you in advance.
//In this list set the path from the different files you want to attach
String[] attachments;
Multipart multipart = new MimeMultipart();
//Add attachments
if(attachments != null && attachments.length > 0) {
for (String str : attachments) {
MimeBodyPart messageBodyPart = new MimeBodyPart();
DataSource source = new FileDataSource(str);
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName(source.getName());
multipart.addBodyPart(messageBodyPart);
}
}
message.setContent(multipart);
I don't have problems uploading huge files, you can try this code.
I used a private mail server of my customer to send emails, and it doesn't show any errors that I can see (because it is a public mail server). I then use Google Mail server, and this is a reply from gmail server to my email account:
Technical details of permanent failure: Google tried to deliver your
message, but it was rejected by the server for the recipient domain
mailinator.com by mail2.mailinator.com. [45.79.147.26].
The error that the other server returned was: 552 5.3.4 Message size
exceeds fixed limit
So this is because the domain mailinator.com has some message size limit so it doesn't appear. I then send things to a gmail email account and it works.

send email with SMTP command, using socket programming in Java

I am trying to send email via socket programming using SMTP commands using socket in java. But i am unable to do so. The problem is in authentication may be.
I need SMTP commands to send email and to authenticate user over server.
Any help appreciated.
Thanks in Advance
Imran
Create Transport Object
Properties props = new Properties();
props.setProperty("mail.transport.protocol", pProtocol);
props.setProperty("mail.host", pHost);
props.setProperty("mail.user", pUser);
props.setProperty("mail.password", pPassword);
mMailSession = Session.getDefaultInstance(props, null);
mMailSession.setDebug(true);
try {
mTransport = mMailSession.getTransport();
mTransport.connect();
} catch (MessagingException e) {
mLog.error(e.getMessage(), e);
throw new MailException(e);
}
Send mail
try {
MimeMessage message = new MimeMessage(mMailSession);
message.setSubject(pSubject);
MimeBodyPart textPart = new MimeBodyPart();
textPart.setContent(pContent, "text/html");
Multipart mp = new MimeMultipart();
mp.addBodyPart(textPart);
message.setContent(mp);
message.addFrom(new Address[] { new InternetAddress(pFrom) });
for (int i = 0; i < pTo.length; i++) {
String tTo = pTo[i];
message.addRecipient(Message.RecipientType.TO, new InternetAddress(tTo));
}
mTransport.sendMessage(message, message.getRecipients(Message.RecipientType.TO));
} catch (MessagingException me) {
throw new MailException(me);
}
EDIT:
After the comment from Thilo, i would like to append, that this solution depend on com.sun.mail and imports javax.mail.* classes.

Categories