use of javax.mail.internet.ContentType in project zm-mailbox by Zimbra.
the class VCard method formatContact.
public static VCard formatContact(Contact con, Collection<String> vcattrs, boolean includeXProps, boolean includeZimbraXProps) {
Map<String, String> fields = con.getFields();
List<Attachment> attachments = con.getAttachments();
List<String> emails = con.getEmailAddresses(DerefGroupMembersOption.NONE);
StringBuilder sb = new StringBuilder();
sb.append("BEGIN:VCARD\r\n");
if (vcattrs == null || vcattrs.contains("VERSION"))
sb.append("VERSION:3.0\r\n");
// FN is a mandatory component of the vCard -- try our best to find or generate one
String fn = fields.get(ContactConstants.A_fullName);
if (vcattrs == null || vcattrs.contains("FN")) {
if (fn == null || fn.trim().equals(""))
try {
fn = con.getFileAsString();
} catch (ServiceException e) {
fn = "";
}
if (fn.trim().equals("") && !emails.isEmpty())
fn = emails.get(0);
if (fn.trim().equals("")) {
String org = fields.get(ContactConstants.A_company);
if (org != null && !org.trim().equals("")) {
fn = org;
}
}
sb.append("FN:").append(vcfEncode(fn)).append("\r\n");
}
if (vcattrs == null || vcattrs.contains("N")) {
StringBuilder nSb = new StringBuilder();
nSb.append(vcfEncode(fields.get(ContactConstants.A_lastName))).append(';').append(vcfEncode(fields.get(ContactConstants.A_firstName))).append(';').append(vcfEncode(fields.get(ContactConstants.A_middleName))).append(';').append(vcfEncode(fields.get(ContactConstants.A_namePrefix))).append(';').append(vcfEncode(fields.get(ContactConstants.A_nameSuffix)));
String n = nSb.toString();
// so, try to avoid that.
if (";;;;".equals(n)) {
n = vcfEncode(fn) + ";;;;";
}
sb.append("N:").append(n).append("\r\n");
}
if (vcattrs == null || vcattrs.contains("NICKNAME"))
encodeField(sb, "NICKNAME", fields.get(ContactConstants.A_nickname));
if (vcattrs == null || vcattrs.contains("PHOTO"))
encodeField(sb, "PHOTO;VALUE=URI", fields.get(ContactConstants.A_image));
if (vcattrs == null || vcattrs.contains("BDAY")) {
String bday = fields.get(ContactConstants.A_birthday);
if (bday != null) {
Date date = DateUtil.parseDateSpecifier(bday);
if (date != null)
sb.append("BDAY;VALUE=date:").append(new SimpleDateFormat("yyyy-MM-dd").format(date)).append("\r\n");
}
}
if (vcattrs == null || vcattrs.contains("ADR")) {
encodeAddress(sb, "home,postal,parcel", ContactConstants.A_homeStreet, ContactConstants.A_homeCity, ContactConstants.A_homeState, ContactConstants.A_homePostalCode, ContactConstants.A_homeCountry, 2, fields);
encodeAddress(sb, "work,postal,parcel", ContactConstants.A_workStreet, ContactConstants.A_workCity, ContactConstants.A_workState, ContactConstants.A_workPostalCode, ContactConstants.A_workCountry, 2, fields);
encodeAddress(sb, "postal,parcel", ContactConstants.A_otherStreet, ContactConstants.A_otherCity, ContactConstants.A_otherState, ContactConstants.A_otherPostalCode, ContactConstants.A_otherCountry, 2, fields);
}
if (vcattrs == null || vcattrs.contains("TEL")) {
// omitting callback phone for now
encodePhone(sb, "car,voice", ContactConstants.A_carPhone, 2, fields);
encodePhone(sb, "home,fax", ContactConstants.A_homeFax, 2, fields);
encodePhone(sb, "home,voice", ContactConstants.A_homePhone, 2, fields);
encodePhone(sb, "cell,voice", ContactConstants.A_mobilePhone, 2, fields);
encodePhone(sb, "fax", ContactConstants.A_otherFax, 2, fields);
encodePhone(sb, "voice", ContactConstants.A_otherPhone, 2, fields);
encodePhone(sb, "pager", ContactConstants.A_pager, 2, fields);
encodePhone(sb, "work,fax", ContactConstants.A_workFax, 2, fields);
encodePhone(sb, "work,voice", ContactConstants.A_workPhone, 2, fields);
}
if (vcattrs == null || vcattrs.contains("EMAIL")) {
encodeField(sb, "EMAIL;TYPE=internet", ContactConstants.A_email, false, 2, fields);
encodeField(sb, "EMAIL;TYPE=internet", "workEmail", true, 1, fields);
}
if (vcattrs == null || vcattrs.contains("URL")) {
encodeField(sb, "URL;TYPE=home", ContactConstants.A_homeURL, false, 2, fields);
encodeField(sb, "URL", ContactConstants.A_otherURL, false, 2, fields);
encodeField(sb, "URL;TYPE=work", ContactConstants.A_workURL, false, 2, fields);
}
if (vcattrs == null || vcattrs.contains("ORG")) {
String org = fields.get(ContactConstants.A_company);
if (org != null && !org.trim().equals("")) {
org = vcfEncode(org);
String dept = fields.get(ContactConstants.A_department);
if (dept != null && !dept.trim().equals("")) {
org += ';' + vcfEncode(dept);
}
sb.append("ORG:").append(org).append("\r\n");
}
}
if (vcattrs == null || vcattrs.contains("TITLE"))
encodeField(sb, "TITLE", fields.get(ContactConstants.A_jobTitle));
if (vcattrs == null || vcattrs.contains("NOTE"))
encodeField(sb, "NOTE", fields.get(ContactConstants.A_notes));
if ((vcattrs == null || vcattrs.contains("PHOTO")) && attachments != null) {
for (Attachment attach : attachments) {
try {
if (attach.getName().equalsIgnoreCase(ContactConstants.A_image)) {
String field = "PHOTO;ENCODING=B";
if (attach.getContentType().startsWith("image/")) {
// We want just the subtype, ignoring any name etc
try {
ContentType ct = new ContentType(attach.getContentType());
if (ct != null) {
String subType = ct.getSubType();
if (!Strings.isNullOrEmpty(subType)) {
field += ";TYPE=" + ct.getSubType().toUpperCase();
}
}
} catch (ParseException e) {
}
}
String encoded = new String(Base64.encodeBase64Chunked(attach.getContent())).trim().replace("\r\n", "\r\n ");
sb.append(field).append(":\r\n ").append(encoded).append("\r\n");
}
} catch (OutOfMemoryError e) {
Zimbra.halt("out of memory", e);
} catch (Throwable t) {
ZimbraLog.misc.info("error fetching attachment content: " + attach.getName(), t);
}
}
}
if (vcattrs == null || vcattrs.contains("KEY")) {
String smimeCert = fields.get(ContactConstants.A_userSMIMECertificate);
if (smimeCert == null) {
smimeCert = fields.get(ContactConstants.A_userCertificate);
}
if (smimeCert != null) {
smimeCert = smimeCert.trim().replace("\r\n", "\r\n ");
String field = "KEY;ENCODING=B";
sb.append(field).append(":\r\n ").append(smimeCert).append("\r\n");
}
}
if (vcattrs == null || vcattrs.contains("CATEGORIES")) {
String[] tags = con.getTags();
if (tags.length > 0) {
StringBuilder sbtags = new StringBuilder();
for (String tagName : tags) {
sbtags.append(sbtags.length() == 0 ? "" : ",").append(vcfEncode(tagName));
}
sb.append("CATEGORIES:").append(sbtags).append("\r\n");
}
}
String uid = getUid(con);
if (vcattrs == null || vcattrs.contains("REV")) {
sb.append("REV:").append(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(new Date(con.getDate()))).append("\r\n");
}
if (vcattrs == null || vcattrs.contains("UID")) {
sb.append("UID:").append(uid).append("\r\n");
}
// sb.append("MAILER:Zimbra ").append(BuildInfo.VERSION).append("\r\n");
if ((vcattrs == null && includeZimbraXProps) || (vcattrs != null && vcattrs.contains("X-ZIMBRA-IMADDRESS"))) {
encodeField(sb, "X-ZIMBRA-IMADDRESS", "imAddress", true, 1, fields);
}
if ((vcattrs == null && includeZimbraXProps) || (vcattrs != null && vcattrs.contains("X-ZIMBRA-ANNIVERSARY"))) {
encodeField(sb, "X-ZIMBRA-ANNIVERSARY", ContactConstants.A_anniversary, false, 2, fields);
}
if ((vcattrs == null && includeZimbraXProps) || (vcattrs != null && vcattrs.contains("X-ZIMBRA-MAIDENNAME"))) {
String maidenName = con.get(ContactConstants.A_maidenName);
if (maidenName != null)
sb.append("X-ZIMBRA-MAIDENNAME:").append(maidenName).append("\r\n");
}
if (includeXProps) {
ListMultimap<String, VCardParamsAndValue> unknownVCardProps = con.getUnknownVCardProps();
for (String key : unknownVCardProps.keySet()) {
for (VCardParamsAndValue paramsAndValue : unknownVCardProps.get(key)) {
StringWriter sw = new StringWriter();
try (FoldingWriter writer = new FoldingWriter(sw)) {
writer.write(key);
String value = paramsAndValue.getValue();
Set<String> params = paramsAndValue.getParams();
if (!params.isEmpty()) {
writer.write(";");
writer.write(Joiner.on(";").join(params));
}
String vcfEncodedValue;
if (params.contains("ENCODING=B")) {
// should be raw BASE64
vcfEncodedValue = value;
} else {
vcfEncodedValue = vcfEncode(value);
}
writer.write(":");
writer.write(vcfEncodedValue);
writer.write("\r\n");
sb.append(sw.toString());
} catch (IOException e) {
ZimbraLog.misc.debug("Problem with adding property '%s' to VCARD - ignoring", key, e);
}
}
}
}
sb.append("END:VCARD\r\n");
return new VCard(fn, sb.toString(), fields, attachments, uid);
}
use of javax.mail.internet.ContentType in project zm-mailbox by Zimbra.
the class Invite method addInlineATTACHes.
protected ZComponent addInlineATTACHes(ZComponent comp) {
MimeMessage mimeMsg = null;
try {
mimeMsg = getMimeMessage();
} catch (ServiceException e1) {
return comp;
}
if (mimeMsg == null) {
return comp;
}
try {
List<MPartInfo> parts = Mime.getParts(mimeMsg, MimeConstants.P_CHARSET_UTF8);
if (parts != null && !parts.isEmpty()) {
for (MPartInfo body : parts.get(0).getChildren()) {
if (body.isMultipart()) {
continue;
}
MimePart mp = body.getMimePart();
String ctype = StringUtil.stripControlCharacters(body.getContentType());
if (MimeConstants.CT_TEXT_CALENDAR.equalsIgnoreCase(ctype)) {
// Otherwise it's just an attachment that happens to be a .ics file.
try {
ContentType ct = new ContentType(body.getMimePart().getContentType());
if (ct.getParameter("method") != null) {
continue;
}
} catch (MessagingException e) {
}
}
String contentType = StringUtil.stripControlCharacters(body.getContentType());
String fileName = Mime.getFilename(mp);
try (InputStream in = mp.getInputStream()) {
byte[] rawBytes = IOUtils.toByteArray(in);
Attach attachment = Attach.fromUnencodedAndContentType(rawBytes, contentType);
if (!Strings.isNullOrEmpty(fileName)) {
attachment.setFileName(fileName);
}
comp.addProperty(attachment.toZProperty());
}
}
}
} catch (MessagingException | IOException e) {
ZimbraLog.calendar.warn("Problem adding inline ATTACHes", e);
}
return comp;
}
use of javax.mail.internet.ContentType in project zm-mailbox by Zimbra.
the class Invite method getDescription.
/**
* Returns the meeting notes. Meeting notes is the text/plain part in an
* invite. It typically includes CUA-generated meeting summary as well as
* text entered by the user.
*
* @return null if notes is not found
* @throws ServiceException
*/
public static String getDescription(Part mmInv, String mimeType) throws ServiceException {
if (mmInv == null)
return null;
try {
// If top-level is text/calendar, parse the iCalendar object and return
// the DESCRIPTION of the first VEVENT/VTODO encountered.
String mmCtStr = mmInv.getContentType();
if (mmCtStr != null) {
ContentType mmCt = new ContentType(mmCtStr);
if (mmCt.match(MimeConstants.CT_TEXT_CALENDAR)) {
boolean wantHtml = MimeConstants.CT_TEXT_HTML.equalsIgnoreCase(mimeType);
Object mmInvContent = mmInv.getContent();
InputStream is = null;
try {
String charset = MimeConstants.P_CHARSET_UTF8;
if (mmInvContent instanceof InputStream) {
charset = mmCt.getParameter(MimeConstants.P_CHARSET);
if (charset == null)
charset = MimeConstants.P_CHARSET_UTF8;
is = (InputStream) mmInvContent;
} else if (mmInvContent instanceof String) {
String str = (String) mmInvContent;
charset = MimeConstants.P_CHARSET_UTF8;
is = new ByteArrayInputStream(str.getBytes(charset));
}
if (is != null) {
ZVCalendar iCal = ZCalendarBuilder.build(is, charset);
for (Iterator<ZComponent> compIter = iCal.getComponentIterator(); compIter.hasNext(); ) {
ZComponent component = compIter.next();
ICalTok compTypeTok = component.getTok();
if (compTypeTok == ICalTok.VEVENT || compTypeTok == ICalTok.VTODO) {
if (!wantHtml)
return component.getPropVal(ICalTok.DESCRIPTION, null);
else
return component.getDescriptionHtml();
}
}
}
} finally {
ByteUtil.closeStream(is);
}
}
}
Object mmInvContent = mmInv.getContent();
if (!(mmInvContent instanceof MimeMultipart)) {
if (mmInvContent instanceof InputStream) {
ByteUtil.closeStream((InputStream) mmInvContent);
}
return null;
}
MimeMultipart mm = (MimeMultipart) mmInvContent;
// If top-level is multipart, get description from text/* part.
int numParts = mm.getCount();
String charset = null;
for (int i = 0; i < numParts; i++) {
BodyPart part = mm.getBodyPart(i);
String ctStr = part.getContentType();
try {
ContentType ct = new ContentType(ctStr);
if (ct.match(mimeType)) {
charset = ct.getParameter(MimeConstants.P_CHARSET);
if (charset == null)
charset = MimeConstants.P_CHARSET_DEFAULT;
byte[] descBytes = ByteUtil.getContent(part.getInputStream(), part.getSize());
return new String(descBytes, charset);
}
// If part is a multipart, recurse.
if (ct.getBaseType().matches(MimeConstants.CT_MULTIPART_WILD)) {
String str = getDescription(part, mimeType);
if (str != null) {
return str;
}
}
} catch (javax.mail.internet.ParseException e) {
ZimbraLog.calendar.warn("Invalid Content-Type found: \"" + ctStr + "\"; skipping part", e);
}
}
} catch (IOException e) {
throw ServiceException.FAILURE("Unable to get calendar item notes MIME part", e);
} catch (MessagingException e) {
throw ServiceException.FAILURE("Unable to get calendar item notes MIME part", e);
}
return null;
}
use of javax.mail.internet.ContentType 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);
}
}
use of javax.mail.internet.ContentType in project zm-mailbox by Zimbra.
the class CalendarMailSender method createForwardedPrivateInviteMessage.
public static MimeMessage createForwardedPrivateInviteMessage(Account account, Locale lc, String method, List<Invite> invites, String origSenderEmail, String forwarderEmail, String[] forwardTo) throws ServiceException {
if (invites == null || invites.isEmpty())
return null;
List<Address> rcpts = new ArrayList<Address>();
for (String to : forwardTo) {
try {
rcpts.add(new JavaMailInternetAddress(to));
} catch (AddressException e) {
ZimbraLog.calendar.warn("Ignoring invalid address \"" + to + "\" during invite forward");
}
}
if (rcpts.isEmpty())
return null;
String subject = L10nUtil.getMessage(MsgKey.calendarSubjectWithheld, lc);
// Create filtered version of invites.
List<Invite> filteredInvs = new ArrayList<Invite>();
for (Invite inv : invites) {
Invite filtered = inv.newCopy();
filtered.clearAlarms();
filtered.clearPrivateInfo();
filtered.setName(subject);
// Add ATTENDEE for forwarder.
List<ZAttendee> atts = inv.getAttendees();
if (atts != null && forwarderEmail != null) {
for (ZAttendee att : atts) {
if (forwarderEmail.equalsIgnoreCase(att.getAddress())) {
filtered.addAttendee(att);
}
}
}
filteredInvs.add(filtered);
}
MimeMessage mm = null;
try {
mm = new Mime.FixedMimeMessage(JMSession.getSmtpSession(account));
mm.setFrom(new JavaMailInternetAddress(origSenderEmail));
mm.addRecipients(RecipientType.TO, rcpts.toArray(new Address[0]));
// Set special header to indicate the forwarding attendee.
mm.setHeader(CalendarMailSender.X_ZIMBRA_CALENDAR_INTENDED_FOR, forwarderEmail);
mm.setSubject(subject);
StringWriter writer = new StringWriter();
try {
writer.write("BEGIN:VCALENDAR\r\n");
ZProperty prop;
prop = new ZProperty(ICalTok.PRODID, ZCalendar.sZimbraProdID);
prop.toICalendar(writer);
prop = new ZProperty(ICalTok.VERSION, ZCalendar.sIcalVersion);
prop.toICalendar(writer);
prop = new ZProperty(ICalTok.METHOD, method);
prop.toICalendar(writer);
// timezones
Invite firstInv = filteredInvs.get(0);
TimeZoneMap tzmap = new TimeZoneMap(firstInv.getTimeZoneMap().getLocalTimeZone());
for (Invite inv : filteredInvs) {
tzmap.add(inv.getTimeZoneMap());
}
for (Iterator<ICalTimeZone> iter = tzmap.tzIterator(); iter.hasNext(); ) {
ICalTimeZone tz = iter.next();
tz.newToVTimeZone().toICalendar(writer);
}
// VEVENTs/VTODOs
for (Invite inv : filteredInvs) {
ZComponent comp = inv.newToVComponent(false, true);
comp.toICalendar(writer);
}
writer.write("END:VCALENDAR\r\n");
} catch (IOException e) {
throw ServiceException.FAILURE("Error writing iCalendar", e);
} finally {
Closeables.closeQuietly(writer);
}
mm.setText(writer.toString());
ContentType ct = new ContentType(MimeConstants.CT_TEXT_CALENDAR);
ct.setParameter(MimeConstants.P_CHARSET, MimeConstants.P_CHARSET_UTF8);
ct.setParameter("method", method);
mm.setHeader("Content-Type", ct.toString());
} catch (MessagingException e) {
ZimbraLog.calendar.warn("Unable to compose email for invite forwarding", e);
}
return mm;
}
Aggregations