I need to develop an application to send events to Gmail / Outlook calendars. Java mail 1.5.5 is used. I did some tests with version 1.6.2, without more success
The chosen solution is to generate ics files, and send them by email to the target calendars adresses.
On Gmail, the email is well recognized as an event email (the email contains the description of the event, the possibility to change the answer, and the event is automatically added to the calendar)
On Outlook, the attachment is not recognized as an event (the email just contains the ics file as an attachment, no description or response request, and the event is not automatically added to the calendar) . You must then click on the attachment, then on "Add to calendar" so that the event is created in the calendar
I found many similar topics on the net, but nothing that helped me solve the problem
The problem could come from the ics file or the headers of the mail. The ics file looks good to me: If on gmail, I create a new message, I add my ics as an attachment, and I send it to my Outlook address, the email is well recognized as an event
Here is the content of the ics file
BEGIN:VCALENDAR
PRODID:<MYPRODID>
VERSION:2.0
CALSCALE:GREGORIAN
METHOD:REQUEST
BEGIN:VEVENT
DTSTAMP:20220629T121224Z
SUMMARY:Test Event
DTSTART:20220630T110000Z
DTEND:20220630T130000Z
UID:<MYUID>
SEQUENCE:1656460800
DESCRIPTION:Event body
ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;RSVP=FALSE;CN=<MYCN>:mailto:<MYEMAIL>
ORGANIZER;CN=<MYORGNAME>:mailto:<MYORGEMAIL>
END:VEVENT
END:VCALENDAR
I have some doubt on the headers / mail structure. I find a lot of different things on the internet, but everything I try leads to the same result (the need to open my email in Outlook, to manually import the attachment)
Here is my java code during the last tests:
Properties prop = new Properties();
prop.put("mail.mime.charset", "UTF-8");
prop.put("mail.smtp.host", "<MYHOST>");
prop.put("mail.smtp.port", "<MYPORT>");
prop.put("mail.smtp.auth", Boolean.TRUE.toString());
prop.put("mail.smtp.user", "<MYUSER>");
prop.put("password", "<MYPASS>");
String from = "<MYORGEMAIL>";
String to = "<MYEMAIL>";
Session session = Session.getInstance(prop, new SMTPAuthenticator(prop));
// Define message
MimeMessage message = new MimeMessage(session);
message.addHeader("method", "REQUEST");
message.addHeader("charset", "UTF-8");
message.addHeader("component", "VEVENT");
message.setFrom(new InternetAddress(from));
message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
message.setSubject("Outlook Meeting Request Using JavaMail");
File invitation = new File("<MYFILEPATH>\\vCalendar_5067936453064913847.ics");
MimeMultipart mixed = new MimeMultipart("mixed");
// Create the message part
MimeMultipart alternative = new MimeMultipart("alternative");
MimeBodyPart alternativePart = new MimeBodyPart();
alternativePart.setContent(alternative);
mixed.addBodyPart(alternativePart);
MimeBodyPart plain = new MimeBodyPart();
plain.setText("body", "UTF-8", "plain");
MimeBodyPart html = new MimeBodyPart();
html.setText("<div dir=\"ltr\">body</div>", "UTF-8", "html");
alternative.addBodyPart(plain);
alternative.addBodyPart(html);
// Create the attachment part
BodyPart icsBodyPart = new MimeBodyPart();
icsBodyPart.addHeader("method", "REQUEST");
icsBodyPart.addHeader("Content-Class", "urn:content-classes:calendarmessage");
icsBodyPart.addHeader("Content-ID", "calendar_message");
icsBodyPart.addHeader("component", "VEVENT");
FileInputStream inputStream = new FileInputStream(invitation.getAbsolutePath());
final DataSource source =
new ByteArrayDataSource(inputStream,
"text/calendar; charset=\"UTF-8\"; name=\"vCalendar_5067936453064913847.ics\"");
icsBodyPart.setDataHandler(new DataHandler(source));
icsBodyPart.setFileName(invitation.getName());
mixed.addBodyPart(icsBodyPart);
// Put parts in message
message.setContent(mixed);
// send message
Transport.send(message);
To know how to structure my mime parts, I look to my message structure in my gmail sendbox (the one that is reconized by Outlook) :
MIME-Version: 1.0
Date: Tue, 12 Jul 2022 14:44:10 +0200
Message-ID: <XXXXXXXXXXX#mail.gmail.com>
Subject: Mail title test
From: XXXXXXXXXXX <XXXXXXXXXXX#gmail.com>
To: XXXXXXXXXXX <XXXXXXXXXXX#XXXXXXXXXXX.com>
Content-Type: multipart/mixed; boundary="00000000000072927505e39b0616"
--00000000000072927505e39b0616
Content-Type: multipart/alternative; boundary="00000000000072927005e39b0614"
--00000000000072927005e39b0614
Content-Type: text/plain; charset="UTF-8"
Mail content test
--00000000000072927005e39b0614
Content-Type: text/html; charset="UTF-8"
<div dir="ltr">Mail content test<br></div>
--00000000000072927005e39b0614--
--00000000000072927505e39b0616
Content-Type: text/calendar; charset="UTF-8"; name="vCalendar_5067936453064913847.ics"
Content-Disposition: attachment; filename="vCalendar_5067936453064913847.ics"
Content-Transfer-Encoding: base64
X-Attachment-Id: f_l4i5zybk0
Content-ID: <f_l4i5zybk0>
QkVHSU46VkNBTEVOREFSClBST0RJRDpTeWxvYiBudWxsClZFUlNJT046Mi4wCkNBTFNDQUxFOkdS
RUdPUklBTgpXXXXXXXXXXXVRVUVTVApCRUdJTjpWRVZFTlQKRFRTVEFNUDoyMDIyMDYyOVQxMjEy
MjRaClNVTU1BUlk6NSAtIMOJdsOpbmVtZW50IGR1IDI4MDYgw6AgU3lsb2IgZGUgZMOpbW8gCkRU
U1RBUlQ6MjAyMjA2MzBUMTEwMDAwWgpEVEVORDoyMDIyMDYzMFQxMzAwMDBaClVJRDp0ZXN0VWlk
MTY1OTc1QHN5bG9iLmNvbQpTRVFVRU5DRToxNjU2NDYwODAwCkRFU0NSSVBUSU9OOlRlc3QgZGUg
Y29ycCBkZSB0ZXh0ZVxuc3VyIHBsdXNpZXVycyBsaWduZXNcLCBhY2NlbnRzIMOgIHRlc3RlcgpB
VFRFTkRFRTtST0xFPVJFUSXXXXXXXXXXXXXOVDtQQVJUU1RBVD1BQ0NFUFRFRDtSU1ZQPUZBTFNF
O0NOPUFsZXhhbmRyZSBORURORUQ6bWFpbHRvOmFsZXgubmVkamFyaUBnbWFpbC5jb20KT1JHQU5J
WkVSO0NOPSJPcmfDom5pc2F0ZXVyIjptYWlsdG86ZGF0YUBzeWxvYi5jb20KRU5EOlZFVkVOVApF
TkQ6VkNBTEVOREFSCgo=
--00000000000072927505e39b0616--
If I knew how to see the same informations on outlook, I could compare the mail received from gmail and the one received from java, but I'm not sure it's possible (I found the "display / message details" option, but this option only show informations about the top level mime part, not the complete mime structure)
Does anyone have an idea how to fix this problem?
Thanks,
I had a similar problem and found a solution in rewriting a Content-Type header. I've added method=REQUEST to this header and after that outlook started recognize my emails as events.
Content-Type: text/calendar; charset="utf-8"; method=REQUEST
Example of code on python:
msg = MIMEMultipart()
msg['Subject'] = 'Your event'
msg['From'] = 'test#test.com'
msg['To'] = 'test#test.com'
with open('example.ics') as f:
event = MIMEText(f.read(), _subtype='calendar', _charset='utf-8')
event.replace_header('Content-Type', 'text/calendar; charset="utf-8"; method=REQUEST')
msg.attach(event)
s.send_message(msg)
s.quit()
Related
I'm developping a ics sender functionnality.
But i have some trouble with office 365 and outlook.
When i sent the ics file to google mail, i don't have any problem.
My event appear in the gmail.
But when i send to outlook or office 365, my appointment didn't appear but it was in the email attachment ( ATT00001.ics).
This is the code send the mail
private void generateIcal(MimeMessage message) throws MessagingException, IOException {
message.addHeaderLine("method=REQUEST");
message.addHeaderLine("charset=UTF-8");
message.addHeaderLine("component=VEVENT");
message.setFrom(new InternetAddress(from));
message.setSubject(subj,"UTF-8");
StringBuffer sb = new StringBuffer();
// Create the message part
BodyPart messageBodyPart = new MimeBodyPart();
// Fill the message
messageBodyPart.setHeader("Content-Class", "urn:content-classes:calendarmessage");
messageBodyPart.setHeader("Content-ID", "calendar_message");
messageBodyPart.setDataHandler(new DataHandler(
new ByteArrayDataSource(txt, "text/calendar;charset=utf-8")));//very important
// Create a Multipart
Multipart multipart = new MimeMultipart();
// Add part one
multipart.addBodyPart(messageBodyPart);
// Put parts in message
message.setContent(multipart);
}
And this generate the ics file
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//TELELANGUE//NONSGML v1.0//EN
BEGIN:VEVENT
DTSTART:20180714T170000Z
DTEND:20180715T035900Z
SUMMARY:Fête à la Bastille
END:VEVENT
END:VCALENDAR
Thanks for your reply
Finally, I found the solution.
Looks like, we need to set "method" and "name" parameters into the BodyPart.
MessageBodyPart.setDataHandler(new DataHandler(
new ByteArrayDataSource(buffer.toString(), "text/calendar;method=REQUEST;name=\"meeting.ics\"")));
1) Parse the ics. file and make it an event in Inbox so that you can read the event information without opening the attachment.
2) Add interactivity so that you can accept/decline the invite directly from Inbox without even opening the ics file. (This is what Gmail has now).
For more information, please see the link below:
incoming calendar invites from outlook are blank
.ics files not showing up in the Outlook.com Inbox?
I am using below code to send mail to multiple users across different domains.
String emailBody = "<html>Some html text goes here</html>"
String from = "from#domain1.com"
String bcc = "bcc#domain2.com"
String subject = "Some subject..."
List attachments = "Some image attachments ..."
MimeMessage message = new MimeMessage(session);
message.setHeader("Content-Type", "text/html; charset=UTF-16")
message.setHeader("Accept-Language", "en-US")
message.setHeader("Content-Language", "en-US")
message.setFrom(new InternetAddress(from));
message.setRecipients(Message.RecipientType.BCC,InternetAddress.parse(bcc));
message.setSubject(subject);
// creates message part
MimeBodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setContent(emailBody, "text/html; charset=UTF-16");
// creates multi-part
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(messageBodyPart);
addAttachmentsToMultiPart(multipart,attachments)
message.setContent(multipart);
Transport.send(message);
The email body is entirely is in English. But users of few domains are recieving it in Chinese characters. When I viewed the html source of the body, I found it is partially garbled. Some orginal html text is intact and some junk characters in between text with no particular order. This mail travels this path "Tomcat application -> company mail server -> outlook.office365.com server -> target mail server -> End user outlook client".
After some research, I found this issue could be due to Character encoding. For testing it, I tried sending this mail to gamil.com. The mail body appears correctly in gmail, but I notice following headers are found in headers part and entire body part is base64 encoded.
Content-Type: text/html; charset="UTF-16"
Content-Transfer-Encoding: base64
I am not sure how "Content-Transfer-Encoding" is being set on headers and where is mail body getting encoded. But I don't see similar headers in End User mail properties. I tried explicitly setting "Content-Transfer-Encoding" to "base64", "quoted-printable" ( and other types), but it is always ignored and gmail always recieves it as base64. And this setting has no impact end user mails. They always recieves same garbage.
Can anyone help me understand what could be issue and how to resolve it
We have code that is very similar to what you have written, the only differences which you could try:
We don't set any headers in the message
We use a slightly different body content type - text/html; charset=utf-8
As an aside, we use com.google.common.net.MediaType to pass the media type into the e-mail sending class, so then you can use MediaType.toString() to get the content type.
I resolved after lot of research and experiment. There were basically two issues
Character-set should not be set at MimeMessage level but at individual MimeBodyPart level.
Changed the UTF-16 to UTF-8. Some email client/server cannot handle UTF-16 properly or they are not configured to handle UTF-16.
I want to add an image to an email along with some text without having to attach the image in the email. Would this be possible ?
I have managed to do the following so far but it is sent with an attachment and also the image in the mail. I want it without an attachment but as a part of the mail
`Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(username));
message.setRecipients(Message.RecipientType.TO,
InternetAddress.parse(emailID));
message.setSubject("Password Reset");
Multipart multipart = new MimeMultipart("related");
BodyPart htmlPart = new MimeBodyPart();
htmlPart.setContent("<html><body>Hi<img src=\"cid:the-img-1\"/></body></html>", "text/html");
multipart.addBodyPart(htmlPart);
BodyPart imgPart=new MimeBodyPart();
// Loading the image
DataSource ds=new FileDataSource("C:\\Users\\XYZ\\Desktop\\images.jpg");
imgPart.setDataHandler(new DataHandler(ds));
//Setting the header
imgPart.setHeader("Content-ID","the-img-1");
multipart.addBodyPart(imgPart);
// attaching the multi-part to the message
message.setContent(multipart);
Transport.send(message);`
You need to construct a multipart/related message.
You will be need to construct an html based e-mail for that purpose.
There are plenty of examples that you can get on google for that.
One example is look at here.
Note that image you want to send should be accessible over http to recipient. May be you can upload it on google drive or some image server
i have using the following code for sending mail within a domain.
public void sendMail(String mailServer, String from, String to,
String subject, String messageBody, String[] attachments)
throws MessagingException, AddressException {
// Setup mail server
Properties props = System.getProperties();
props.put("mail.smtp.host", mailServer);
// Get a mail session
Session session = Session.getDefaultInstance(props, null);
// Define a new mail message
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
message.setSubject(subject);
// Create a message part to represent the body text
BodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setText(messageBody);
// use a MimeMultipart as we need to handle the file attachments
Multipart multipart = new MimeMultipart();
// add the message body to the mime message
multipart.addBodyPart(messageBodyPart);
// add any file attachments to the message
addAtachments(attachments, multipart);
// Put all message parts in the message
message.setContent(multipart);
// Send the message
Transport.send(message);
System.err.println("Message Send");
}
protected void addAtachments(String[] attachments, Multipart multipart)
throws MessagingException, AddressException {
for (int i = 0; i < attachments.length ; i++) {
String filename = attachments[i];
MimeBodyPart attachmentBodyPart = new MimeBodyPart();
// use a JAF FileDataSource as it does MIME type detection
DataSource source = new FileDataSource(filename);
attachmentBodyPart.setDataHandler(new DataHandler(source));
// assume that the filename you want to send is the same as the
// actual file name - could alter this to remove the file path
attachmentBodyPart.setFileName(filename);
// add the attachment
multipart.addBodyPart(attachmentBodyPart);
}
}
but if with the same code i try to send an email outside the domain, say i am sending email from mjsharma#domain.com to mhsharma#gmail,com then it fails and gives me the following error. 550 5.7.1 Rcpt command failed: Mail denied due to site's policy
Am i missing something in the above code.
Please help me
I suspect that's not a problem in your code, but in your mail server (sendmail?) configuration. I would talk to whoever administers your mail infrastructure.
It's likely that your local mail server requires you to authenticate before sending mail out into the world. This is a common policy to prevent spammers from relaying their mail through it.
Assuming your machine has Outlook installed... have you tried using moyosoft's java outlook connector? it's pretty simple to use and passes through network restrictions because it connects to your Outlook application and then sends the mail, so any restriction on smtp ports or servers/proxy policies will be ignored if your Outlook client is working fine.
if you are doing it with command line server-side then i guess this answer is useless for you.
Source: i had similar problem (not same error code, more like an intranet restriction) and using this library solved my problem because of the posted above.
Anybody knows how to do this? I got all the information of the email (body, subject, from , to, cc, bcc) and need to generate an .eml file out of it.
You can create eml files with the following code. It works fine with thunderbird and probably with other email clients:
public static void createMessage(String to, String from, String subject, String body, List<File> attachments) {
try {
Message message = new MimeMessage(Session.getInstance(System.getProperties()));
message.setFrom(new InternetAddress(from));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
message.setSubject(subject);
// create the message part
MimeBodyPart content = new MimeBodyPart();
// fill message
content.setText(body);
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(content);
// add attachments
for(File file : attachments) {
MimeBodyPart attachment = new MimeBodyPart();
DataSource source = new FileDataSource(file);
attachment.setDataHandler(new DataHandler(source));
attachment.setFileName(file.getName());
multipart.addBodyPart(attachment);
}
// integration
message.setContent(multipart);
// store file
message.writeTo(new FileOutputStream(new File("c:/mail.eml")));
} catch (MessagingException ex) {
Logger.getLogger(Mailkit.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(Mailkit.class.getName()).log(Level.SEVERE, null, ex);
}
}
You can construct javax.mail.Message object (or have it already constructed from the mail server) and then you can use writeTo() method to save it to file.
See JavaMail API for more information.
EML files are just plain text files. The headers are separated from the body by a blank line. Headers look like this:
From: "DR CLEMENT OKON" <drclement#nigerianspam.com>
To: "You" <you#yourdomain.com>
Subject: REQUEST FOR URGENT BUSINESS RELATIONSHIP
Date: Tue, 30 Sep 2008 09:42:47 -0400
For more info, the official spec is RFC 2822. It's actually not as hard to read as some RFCs.
Edit: When I said "plain text" I should have thought for a second. I really meant plain ASCII - and not the 8-bit "extended ASCII" either - just up to character 127. If you want more than seven bits, you need some kind of encoding and things get complicated.
Looking at a typical EML file it looks like a raw dump of the text communication that went to the server. So it is a text file containing the mail headers and body. To get your attachments, different views, etc in the correct format inside the EML file you need to MIME-encode the body and its parts.
If you want to add HTML Stuff you have to add
content.setHeader("Content-Type", "text/html");
(as Marco Sulla said) but also change
message.setContent(multipart);
to
message.setContent(multipart,"text/html");