use of com.zimbra.common.zmime.ZMimeMultipart in project zm-mailbox by Zimbra.
the class ParseMimeMessage method setContent.
/**
* The <mp>'s from the client and the MimeBodyParts in alternatives[] all want to be "content"
* of this MimeMessage. The alternatives[] all need to be "alternative" to whatever the client sends
* us....but we want to be careful so that we do NOT create a nested multipart/alternative structure
* within another one (that would be very tacky)....so this is a bit complicated.
*/
private static void setContent(MimeMessage mm, MimeMultipart mmp, Element elem, MimeBodyPart[] alternatives, ParseMessageContext ctxt) throws MessagingException, ServiceException, IOException {
String type = elem.getAttribute(MailConstants.A_CONTENT_TYPE, MimeConstants.CT_DEFAULT).trim();
ContentType ctype = new ContentType(type, ctxt.use2231).cleanup();
// is the client passing us a multipart?
if (ctype.getPrimaryType().equals("multipart")) {
// handle multipart content separately...
setMultipartContent(ctype, mm, mmp, elem, alternatives, ctxt);
return;
}
Element inline = elem.getOptionalElement(MailConstants.E_ATTACH);
if (inline != null) {
handleAttachments(inline, mmp, ctxt, elem.getAttribute(MailConstants.A_CONTENT_ID, null), Part.INLINE);
return;
}
if (alternatives != null) {
// create a multipart/alternative to hold all the alternatives
MimeMultipart mmpNew = new ZMimeMultipart("alternative");
if (mmp == null) {
mm.setContent(mmpNew);
} else {
MimeBodyPart mbpWrapper = new ZMimeBodyPart();
mbpWrapper.setContent(mmpNew);
mmp.addBodyPart(mbpWrapper);
}
mmp = mmpNew;
}
// once we get here, mmp is either NULL, a multipart/mixed from the toplevel,
// or a multipart/alternative created just above....either way we are safe to stick
// the client's nice and simple body right here
String text = elem.getAttribute(MailConstants.E_CONTENT, "");
byte[] raw = text.getBytes(Charsets.UTF_8);
if (raw.length > 0 || !LC.mime_exclude_empty_content.booleanValue() || ctype.getPrimaryType().equals("text")) {
ctxt.incrementSize("message body", raw.length);
// if the user has specified an alternative charset, make sure it exists and can encode the content
String charset = CharsetUtil.checkCharset(text, ctxt.defaultCharset);
ctype.setCharset(charset).setParameter(MimeConstants.P_CHARSET, charset);
Object content = ctype.getContentType().equals(ContentType.MESSAGE_RFC822) ? new ZMimeMessage(JMSession.getSession(), new SharedByteArrayInputStream(raw)) : text;
if (mmp != null) {
MimeBodyPart mbp = new ZMimeBodyPart();
mbp.setContent(content, ctype.toString());
mmp.addBodyPart(mbp);
} else {
mm.setContent(content, ctype.toString());
}
}
if (alternatives != null) {
for (int i = 0; i < alternatives.length; i++) {
ctxt.incrementSize("alternative body", alternatives[i].getSize());
mmp.addBodyPart(alternatives[i]);
}
}
}
use of com.zimbra.common.zmime.ZMimeMultipart in project zm-mailbox by Zimbra.
the class SendDeliveryReport method sendReport.
public static void sendReport(Account authAccount, Message msg, boolean automatic, String requestHost, String userAgent) throws ServiceException {
MimeMessage mm = msg.getMimeMessage();
Account owner = msg.getMailbox().getAccount();
String charset = authAccount.getPrefMailDefaultCharset();
if (charset == null) {
charset = MimeConstants.P_CHARSET_UTF8;
}
try {
InternetAddress[] recipients = Mime.parseAddressHeader(mm, "Disposition-Notification-To");
if (recipients == null || recipients.length == 0)
return;
SMTPMessage report = new SMTPMessage(JMSession.getSmtpSession());
String subject = "Read-Receipt: " + msg.getSubject();
report.setSubject(subject, CharsetUtil.checkCharset(subject, charset));
report.setSentDate(new Date());
report.setFrom(AccountUtil.getFriendlyEmailAddress(authAccount));
report.addRecipients(javax.mail.Message.RecipientType.TO, recipients);
report.setHeader("Auto-Submitted", "auto-replied (zimbra; read-receipt)");
report.setHeader("Precedence", "bulk");
if (Provisioning.getInstance().getConfig().isAutoSubmittedNullReturnPath()) {
report.setEnvelopeFrom("<>");
} else {
report.setEnvelopeFrom(authAccount.getName());
}
MimeMultipart multi = new ZMimeMultipart("report");
// part 1: human-readable notification
String text = generateTextPart(owner, mm, authAccount.getLocale());
MimeBodyPart mpText = new ZMimeBodyPart();
mpText.setText(text, CharsetUtil.checkCharset(text, charset));
multi.addBodyPart(mpText);
// part 2: disposition notification
String mdn = generateReport(owner, mm, automatic, requestHost, userAgent);
MimeBodyPart mpMDN = new ZMimeBodyPart();
mpMDN.setText(mdn, MimeConstants.P_CHARSET_UTF8);
mpMDN.setHeader("Content-Type", "message/disposition-notification; charset=utf-8");
multi.addBodyPart(mpMDN);
// // part 3: original message
// MimeBodyPart mpOriginal = new ZMimeBodyPart();
// mpOriginal.setDataHandler(new DataHandler(new BlobDataSource(msg.getBlob())));
// mpOriginal.setHeader("Content-Type", MimeConstants.CT_MESSAGE_RFC822);
// mpOriginal.setHeader("Content-Disposition", Part.ATTACHMENT);
// multi.addBodyPart(mpOriginal);
report.setContent(multi);
report.setHeader("Content-Type", multi.getContentType() + "; report-type=disposition-notification");
report.saveChanges();
Transport.send(report);
} catch (MessagingException me) {
throw ServiceException.FAILURE("error while sending read receipt", me);
}
}
use of com.zimbra.common.zmime.ZMimeMultipart in project zm-mailbox by Zimbra.
the class ParseMimeMessage method setMultipartContent.
private static void setMultipartContent(ContentType contentType, MimeMessage mm, MimeMultipart mmp, Element elem, MimeBodyPart[] alternatives, ParseMessageContext ctxt) throws MessagingException, ServiceException, IOException {
// do we need to add a multipart/alternative for the alternatives?
if (alternatives == null || contentType.getSubType().equals("alternative")) {
// no need to add an extra multipart/alternative!
// create the MimeMultipart and attach it to the existing structure:
MimeMultipart mmpNew = new ZMimeMultipart(contentType);
if (mmp == null) {
// there were no multiparts at all, we need to create one
mm.setContent(mmpNew);
} else {
// there was already a multipart/mixed at the top of the mm
MimeBodyPart mbpWrapper = new ZMimeBodyPart();
mbpWrapper.setContent(mmpNew);
mmp.addBodyPart(mbpWrapper);
}
// add each part in turn (recursively) below
for (Element subpart : elem.listElements()) {
setContent(mm, mmpNew, subpart, null, ctxt);
}
// finally, add the alternatives if there are any...
if (alternatives != null) {
for (int i = 0; i < alternatives.length; i++) {
ctxt.incrementSize("alternative", alternatives[i].getSize());
mmpNew.addBodyPart(alternatives[i]);
}
}
} else {
// create a multipart/alternative to hold all the client's struct + the alternatives
MimeMultipart mmpNew = new ZMimeMultipart("alternative");
if (mmp == null) {
mm.setContent(mmpNew);
} else {
MimeBodyPart mbpWrapper = new ZMimeBodyPart();
mbpWrapper.setContent(mmpNew);
mmp.addBodyPart(mbpWrapper);
}
// add the entire client's multipart/whatever here inside our multipart/alternative
setContent(mm, mmpNew, elem, null, ctxt);
// add all the alternatives
for (int i = 0; i < alternatives.length; i++) {
ctxt.incrementSize("alternative", alternatives[i].getSize());
mmpNew.addBodyPart(alternatives[i]);
}
}
}
use of com.zimbra.common.zmime.ZMimeMultipart in project zm-mailbox by Zimbra.
the class CalendarMailSender method createForwardNotifyMessage.
public static MimeMessage createForwardNotifyMessage(Account senderAcct, Account toAcct, String to, Address[] rcpts, Invite inv) throws MessagingException, ServiceException {
MimeMessage mm = new Mime.FixedMimeMessage(JMSession.getSession());
Locale lc = toAcct.getLocale();
mm.setSubject(L10nUtil.getMessage(MsgKey.calendarForwardNotificationSubject, lc, inv.getName()), MimeConstants.P_CHARSET_UTF8);
mm.setSentDate(new Date());
String postmaster = senderAcct.getAttr(Provisioning.A_zimbraNewMailNotificationFrom);
Map<String, String> vars = new HashMap<String, String>();
vars.put("RECIPIENT_DOMAIN", senderAcct.getDomainName());
postmaster = StringUtil.fillTemplate(postmaster, vars);
mm.setSender(new JavaMailInternetAddress(postmaster));
mm.setFrom(new JavaMailInternetAddress(senderAcct.getName()));
mm.setRecipient(RecipientType.TO, new JavaMailInternetAddress(to));
MimeMultipart mmp = new ZMimeMultipart("alternative");
mm.setContent(mmp);
String sender = senderAcct.getCn() + " <" + senderAcct.getName() + ">";
String time = FriendlyCalendaringDescription.getTimeDisplayString(inv.getStartTime(), inv.getEndTime(), inv.isRecurrence(), inv.isAllDayEvent(), lc, toAcct);
StringBuilder sb = new StringBuilder();
StringBuilder sbHtml = new StringBuilder();
for (Address rcpt : rcpts) {
sb.append(rcpt.toString()).append("\n\t");
InternetAddress address = new JavaMailInternetAddress(rcpt.toString());
sbHtml.append("<a href=\"mailto:").append(address.getAddress()).append("\">");
if (address.getPersonal() != null) {
sbHtml.append(address.getPersonal()).append("</a>").append("<br>");
} else {
sbHtml.append(address.getAddress()).append("</a>").append("<br>");
}
}
String recipients = sb.toString();
String recipientsHtml = sbHtml.toString();
if (inv.isRecurrence()) {
ZRecur zr = FriendlyCalendaringDescription.getRecur(inv);
time += " (" + FriendlyCalendaringDescription.getRecurrenceDisplayString(zr, inv.getStartTime().getCalendarCopy(), lc) + ")";
}
String text = L10nUtil.getMessage(MsgKey.calendarForwardNotificationBody, lc, sender, inv.getName(), time, recipients);
MimeBodyPart textPart = new ZMimeBodyPart();
textPart.setText(text, MimeConstants.P_CHARSET_UTF8);
mmp.addBodyPart(textPart);
sender = "<a href=\"mailto:" + senderAcct.getName() + "\">" + senderAcct.getCn() + "</a>";
String html = L10nUtil.getMessage(MsgKey.calendarForwardNotificationBodyHtml, lc, sender, inv.getName(), time, recipientsHtml);
MimeBodyPart htmlPart = new ZMimeBodyPart();
htmlPart.setContent(html, MimeConstants.CT_TEXT_HTML + "; " + MimeConstants.P_CHARSET + "=" + MimeConstants.P_CHARSET_UTF8);
mmp.addBodyPart(htmlPart);
mm.saveChanges();
return mm;
}
use of com.zimbra.common.zmime.ZMimeMultipart in project zm-mailbox by Zimbra.
the class CalendarMailSender method createCalendarMessage.
public static MimeMessage createCalendarMessage(Account account, Address fromAddr, Address senderAddr, List<Address> toAddrs, String subject, String desc, String descHtml, String uid, ZCalendar.ZVCalendar cal, List<Attach> attaches, boolean replyToSender) throws ServiceException {
if (desc == null)
desc = "";
try {
MimeMessage mm = new Mime.FixedMimeMessage(JMSession.getSmtpSession(account));
MimeMultipart mpAlternatives = new ZMimeMultipart("alternative");
if (attaches != null && !attaches.isEmpty()) {
MimeMultipart mpMixed = new ZMimeMultipart("mixed");
mm.setContent(mpMixed);
MimeBodyPart mbpWrapper = new ZMimeBodyPart();
mbpWrapper.setContent(mpAlternatives);
mpMixed.addBodyPart(mbpWrapper);
for (Attach attach : attaches) {
byte[] rawData = attach.getDecodedData();
if (rawData == null) {
continue;
}
ContentDisposition cdisp = new ContentDisposition(Part.ATTACHMENT, true);
String ctypeAsString = attach.getContentType();
if (ctypeAsString == null) {
ctypeAsString = MimeConstants.CT_APPLICATION_OCTET_STREAM;
}
ContentType ctype = new ContentType(ctypeAsString);
if (attach.getFileName() != null) {
ctype.setParameter("name", attach.getFileName());
cdisp.setParameter("filename", attach.getFileName());
}
MimeBodyPart mbp2 = new ZMimeBodyPart();
ByteArrayDataSource bads = new ByteArrayDataSource(rawData, ctypeAsString);
mbp2.setDataHandler(new DataHandler(bads));
mbp2.setHeader("Content-Type", ctype.toString());
mbp2.setHeader("Content-Disposition", cdisp.toString());
mbp2.setHeader("Content-Transfer-Encoding", "base64");
mpMixed.addBodyPart(mbp2);
}
} else {
mm.setContent(mpAlternatives);
}
// Add the text as DESCRIPTION property in the iCalendar part.
// MS Entourage for Mac wants this. It ignores text/plain and
// text/html MIME parts.
cal.addDescription(desc, null);
// ///////
// TEXT part (add me first!)
MimeBodyPart textPart = new ZMimeBodyPart();
textPart.setText(desc, MimeConstants.P_CHARSET_UTF8);
mpAlternatives.addBodyPart(textPart);
// HTML part is needed to keep Outlook happy as it doesn't know
// how to deal with a message with only text/plain but no HTML.
MimeBodyPart htmlPart = new ZMimeBodyPart();
if (descHtml != null) {
ContentType ct = new ContentType(MimeConstants.CT_TEXT_HTML);
ct.setParameter(MimeConstants.P_CHARSET, MimeConstants.P_CHARSET_UTF8);
htmlPart.setText(descHtml, MimeConstants.P_CHARSET_UTF8);
htmlPart.setHeader("Content-Type", ct.toString());
} else {
htmlPart.setDataHandler(new DataHandler(new HtmlPartDataSource(desc)));
}
mpAlternatives.addBodyPart(htmlPart);
// ///////
// CALENDAR part
MimeBodyPart icalPart = makeICalIntoMimePart(cal);
mpAlternatives.addBodyPart(icalPart);
// MESSAGE HEADERS
if (subject != null) {
mm.setSubject(subject, MimeConstants.P_CHARSET_UTF8);
}
if (toAddrs != null) {
Address[] addrs = new Address[toAddrs.size()];
toAddrs.toArray(addrs);
mm.addRecipients(javax.mail.Message.RecipientType.TO, addrs);
}
if (fromAddr != null)
mm.setFrom(fromAddr);
if (senderAddr != null) {
mm.setSender(senderAddr);
if (replyToSender) {
mm.setReplyTo(new Address[] { senderAddr });
}
}
mm.setSentDate(new Date());
mm.saveChanges();
return mm;
} catch (MessagingException e) {
throw ServiceException.FAILURE("Messaging Exception while building MimeMessage from invite", e);
}
}
Aggregations