use of javax.mail.internet.MimeMultipart in project zm-mailbox by Zimbra.
the class FilterUtil method reject.
public static void reject(OperationContext octxt, Mailbox mailbox, ParsedMessage parsedMessage, String reason, LmtpEnvelope envelope) throws MessagingException, ServiceException {
MimeMessage mimeMessage = parsedMessage.getMimeMessage();
if (isMailLoop(mailbox, mimeMessage, new String[] { HEADER_FORWARDED })) {
// Detected a mail loop. Do not send MDN, but just discard the message
String error = String.format("Detected a mail loop for message %s. No MDN sent.", Mime.getMessageID(mimeMessage));
ZimbraLog.filter.info(error);
throw ServiceException.FAILURE(error, null);
}
String reportTo = null;
if (envelope != null && envelope.hasSender()) {
reportTo = envelope.getSender().getEmailAddress();
}
if (reportTo == null || reportTo.isEmpty()) {
String[] returnPath = mimeMessage.getHeader(HEADER_RETURN_PATH);
if (returnPath == null || returnPath.length == 0) {
// >> NOT be generated if the MAIL FROM (or Return-Path) is empty.
throw new MessagingException("Neither 'envelope from' nor 'Return-Path' specified. Can't locate the address to reject to (No MDN sent)");
} else {
// At least one 'return-path' should exist.
reportTo = returnPath[0];
}
}
Account owner = mailbox.getAccount();
Locale locale = owner.getLocale();
String charset = owner.getPrefMailDefaultCharset();
if (charset == null) {
charset = MimeConstants.P_CHARSET_UTF8;
}
SMTPMessage report = new SMTPMessage(JMSession.getSmtpSession());
// add the forwarded header account names to detect the mail loop between accounts
for (String headerFwdAccountName : Mime.getHeaders(mimeMessage, HEADER_FORWARDED)) {
report.addHeader(HEADER_FORWARDED, headerFwdAccountName);
}
report.addHeader(HEADER_FORWARDED, owner.getName());
// MDN header
report.setEnvelopeFrom("<>");
report.setRecipient(javax.mail.Message.RecipientType.TO, new JavaMailInternetAddress(reportTo));
String subject = L10nUtil.getMessage(MsgKey.seiveRejectMDNSubject, locale);
report.setSubject(subject);
report.setSentDate(new Date());
InternetAddress address = new JavaMailInternetAddress(owner.getName());
report.setFrom(address);
MimeMultipart multi = new ZMimeMultipart("report");
// part 1: human-readable notification
String text = L10nUtil.getMessage(MsgKey.seiveRejectMDNErrorMsg, locale) + "\n" + reason;
MimeBodyPart mpText = new ZMimeBodyPart();
mpText.setText(text, CharsetUtil.checkCharset(text, charset));
multi.addBodyPart(mpText);
// part 2: disposition notification
StringBuilder mdn = new StringBuilder();
mdn.append("Final-Recipient: rfc822;").append(owner.getName()).append("\r\n");
mdn.append("Disposition: automatic-action/MDN-sent-automatically");
mdn.append("; deleted\r\n");
MimeBodyPart mpMDN = new ZMimeBodyPart();
mpMDN.setText(mdn.toString(), MimeConstants.P_CHARSET_UTF8);
mpMDN.setHeader("Content-Type", "message/disposition-notification; charset=utf-8");
multi.addBodyPart(mpMDN);
// Assemble the MDN
report.setContent(multi);
report.setHeader("Content-Type", multi.getContentType() + "; report-type=disposition-notification");
report.saveChanges();
MailSender mailSender = mailbox.getMailSender().setSaveToSent(false);
mailSender.setRecipients(reportTo);
mailSender.setEnvelopeFrom("<>");
mailSender.sendMimeMessage(octxt, mailbox, report);
}
use of javax.mail.internet.MimeMultipart in project zm-mailbox by Zimbra.
the class CalendarItem method createBlob.
/**
* The Blob for the appointment/task is currently single Mime multipart/digest which has
* each invite's MimeMessage stored as a part.
*
* @param invPm
* @param firstInvite
* @throws ServiceException
*/
private MailboxBlob createBlob(ParsedMessage invPm, Invite firstInvite) throws ServiceException {
// Create blob only if there's an attachment or DESCRIPTION is too big to be stored in metadata.
if (!firstInvite.hasAttachment() && (invPm == null || firstInvite.descInMeta())) {
// If we're not going to create a blob after all, we must at least save the metadata to db.
// It's weird that the db update is implicitly required of this method, but that's the way
// it is, unfortunately. If we're creating a blob, the implicit db update is done by
// storeUpdatedBlob() call. (see below)
saveMetadata();
return null;
}
try {
// create the toplevel multipart/digest...
MimeMessage mm = new Mime.FixedMimeMessage(JMSession.getSession());
MimeMultipart mmp = new ZMimeMultipart("digest");
mm.setContent(mmp);
// add the invite
MimeBodyPart mbp = new ZMimeBodyPart();
mbp.setDataHandler(new DataHandler(new PMDataSource(invPm)));
mbp.addHeader("invId", Integer.toString(firstInvite.getMailItemId()));
mmp.addBodyPart(mbp);
mm.saveChanges();
return storeUpdatedBlob(mm);
} catch (MessagingException e) {
throw ServiceException.FAILURE("MessagingException " + e, e);
} catch (IOException e) {
throw ServiceException.FAILURE("IOException " + e, e);
}
}
use of javax.mail.internet.MimeMultipart in project zm-mailbox by Zimbra.
the class ParsedContact method generateMimeMessage.
private static MimeMessage generateMimeMessage(List<Attachment> attachments) throws MessagingException {
MimeMessage mm = new Mime.FixedMimeMessage(JMSession.getSession());
MimeMultipart multi = new ZMimeMultipart("mixed");
int part = 1;
for (Attachment attach : attachments) {
ContentDisposition cdisp = new ContentDisposition(Part.ATTACHMENT);
cdisp.setParameter("filename", attach.getFilename()).setParameter("field", attach.getName());
MimeBodyPart bp = new ZMimeBodyPart();
// it gets called before setting Content-Type and CTE headers.
try {
bp.setDataHandler(new DataHandler(new ByteArrayDataSource(attach.getContent(), attach.getContentType())));
} catch (IOException e) {
throw new MessagingException("could not generate mime part content", e);
}
bp.addHeader("Content-Disposition", cdisp.toString());
bp.addHeader("Content-Type", attach.getContentType());
bp.addHeader("Content-Transfer-Encoding", MimeConstants.ET_8BIT);
multi.addBodyPart(bp);
attach.setPartName(Integer.toString(part++));
}
mm.setContent(multi);
mm.saveChanges();
return mm;
}
use of javax.mail.internet.MimeMultipart in project zm-mailbox by Zimbra.
the class MimeVisitor method accept.
private final synchronized boolean accept(MimePart mp, int depth) throws MessagingException {
// do not recurse beyond a fixed depth
if (depth >= MAX_VISITOR_DEPTH)
return false;
boolean modified = false;
if (mp instanceof MimeMessage)
modified |= visitMessage((MimeMessage) mp, VisitPhase.VISIT_BEGIN);
String ctype = Mime.getContentType(mp);
boolean isMultipart = ctype.startsWith(MimeConstants.CT_MULTIPART_PREFIX);
boolean isMessage = !isMultipart && ctype.equals(MimeConstants.CT_MESSAGE_RFC822);
if (isMultipart) {
Object content = null;
try {
content = Mime.getMultipartContent(mp, ctype);
} catch (Exception e) {
ZimbraLog.extensions.warn("could not fetch multipart content; skipping", e);
}
if (content instanceof MimeMultipart) {
MimeMultipart multi = (MimeMultipart) content;
boolean multiModified = false;
if (visitMultipart(multi, VisitPhase.VISIT_BEGIN))
modified = multiModified = true;
try {
for (int i = 0; i < multi.getCount(); i++) {
BodyPart bp = multi.getBodyPart(i);
if (bp instanceof MimeBodyPart) {
if (accept((MimeBodyPart) bp, depth + 1))
modified = multiModified = true;
} else {
ZimbraLog.extensions.info("unexpected BodyPart subclass: " + bp.getClass().getName());
}
}
} catch (MessagingException e) {
ZimbraLog.extensions.warn("could not fetch body subpart; skipping remainder", e);
}
if (visitMultipart(multi, VisitPhase.VISIT_END))
modified = multiModified = true;
if (multiModified)
mp.setContent(multi);
}
} else if (isMessage) {
MimeMessage content = null;
try {
content = Mime.getMessageContent(mp);
} catch (Exception e) {
ZimbraLog.extensions.warn("could not fetch attached message content; skipping", e);
}
if (content != null)
modified |= accept(content, depth + 1);
} else if (mp instanceof MimeBodyPart) {
modified |= visitBodyPart((MimeBodyPart) mp);
} else if (!(mp instanceof MimeMessage)) {
ZimbraLog.extensions.info("unexpected MimePart subclass: " + mp.getClass().getName() + " (ctype='" + ctype + "')");
}
if (mp instanceof MimeMessage) {
MimeMessage mm = (MimeMessage) mp;
modified |= visitMessage(mm, VisitPhase.VISIT_END);
// commit changes to the message
if (modified)
mm.saveChanges();
}
return modified;
}
use of javax.mail.internet.MimeMultipart in project zm-mailbox by Zimbra.
the class Mime method listParts.
private static List<MPartInfo> listParts(MimePart root, String defaultCharset) throws MessagingException, IOException {
List<MPartInfo> parts = new ArrayList<MPartInfo>();
LinkedList<MPartInfo> queue = new LinkedList<MPartInfo>();
queue.add(generateMPartInfo(root, null, "", 0));
MimeMultipart emptyMultipart = null;
while (!queue.isEmpty()) {
MPartInfo mpart = queue.removeFirst();
MimePart mp = mpart.getMimePart();
parts.add(mpart);
String cts = mpart.mContentType;
boolean isMultipart = cts.startsWith(MimeConstants.CT_MULTIPART_PREFIX);
boolean isMessage = !isMultipart && cts.equals(MimeConstants.CT_MESSAGE_RFC822);
if (isMultipart) {
// IMAP part numbering is screwy: top-level multipart doesn't get a number
String prefix = mpart.mPartName.length() > 0 ? (mpart.mPartName + '.') : "";
if (mp instanceof MimeMessage) {
mpart.mPartName = prefix + "TEXT";
}
MimeMultipart multi = getMultipartContent(mp, cts);
if (multi != null) {
if (multi.getCount() == 0 && LC.mime_promote_empty_multipart.booleanValue()) {
if (emptyMultipart == null) {
emptyMultipart = multi;
}
if (MimeConstants.CT_MULTIPART_APPLEDOUBLE.equalsIgnoreCase(getContentType(mp))) {
ZimbraLog.misc.debug("appledouble with no children; assuming it is malformed and really applefile");
mpart.mContentType = mpart.mContentType.replace(MimeConstants.CT_MULTIPART_APPLEDOUBLE, MimeConstants.CT_APPLEFILE);
}
}
mpart.mChildren = new ArrayList<MPartInfo>(multi.getCount());
for (int i = 1; i <= multi.getCount(); i++) {
mpart.mChildren.add(generateMPartInfo((MimePart) multi.getBodyPart(i - 1), mpart, prefix + i, i));
}
queue.addAll(0, mpart.mChildren);
}
} else if (isMessage) {
MimeMessage mm = getMessageContent(mp);
if (mm != null) {
MPartInfo child = generateMPartInfo(mm, mpart, mpart.mPartName, 0);
queue.addFirst(child);
mpart.mChildren = Arrays.asList(child);
}
} else {
// nothing to do at this stage
}
}
if (emptyMultipart != null && parts.size() == 1) {
String text = emptyMultipart.getPreamble();
if (!StringUtil.isNullOrEmpty(text)) {
ZimbraLog.misc.debug("single multipart with no children. promoting the preamble into a single text part");
parts.remove(0);
MPartInfo mpart = new MPartInfo();
ZMimeBodyPart mp = new ZMimeBodyPart();
mp.setText(text, defaultCharset);
mpart.mPart = mp;
mpart.mContentType = mp.getContentType();
mpart.mDisposition = "";
mpart.mPartName = "1";
parts.add(mpart);
}
}
return parts;
}
Aggregations