Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

keep timezone when parsing

  • Loading branch information...
commit 68ba395ea48ea1fa693c37931247159073337815 1 parent 159aece
@azinman authored
View
2  sitebricks-mail/src/main/java/com/google/sitebricks/mail/NettyImapClient.java
@@ -686,7 +686,7 @@ private static String toUpperBound(int end) {
argsBuilder.append(',');
}
// argsBuilder.append(')');
- argsBuilder.append(" (RFC822.SIZE FLAGS INTERNALDATE BODYSTRUCTURE ENVELOPE UID");
+ argsBuilder.append(" (RFC822.SIZE FLAGS INTERNALDATE ENVELOPE UID");
if (config.useGmailExtensions()) {
argsBuilder.append(" X-GM-MSGID X-GM-THRID X-GM-LABELS");
}
View
10 sitebricks-mail/src/main/java/com/google/sitebricks/mail/imap/Message.java
@@ -24,6 +24,7 @@
// A header can have multiple, different values.
private Multimap<String, String> headers = newListMultimap();
private List<BodyPart> bodyParts = new ArrayList<BodyPart>();
+ private String rootMimeType = null;
public void setImapUid(int imapUid) {
this.imapUid = imapUid;
@@ -67,7 +68,14 @@ public void setStatus(MessageStatus status) {
}
@Override public void setMimeType(String mimeType) {
- throw new RuntimeException("Should not call mimeType from here");
+ if (!mimeType.startsWith("multipart")) {
+ throw new RuntimeException("Invalid root mimeType: " + mimeType);
+ }
+ this.rootMimeType = mimeType;
+ }
+
+ public String getRootMimeType() {
+ return rootMimeType;
}
public static class BodyPart implements HasBodyParts {
View
8 sitebricks-mail/src/main/java/com/google/sitebricks/mail/imap/MessageStatus.java
@@ -11,7 +11,7 @@
public class MessageStatus {
private int imapUid;
private String messageUid;
- private Date receivedDate;
+ private GregorianCalendar receivedDate;
private String subject;
private String inReplyTo;
@@ -100,7 +100,7 @@ public String getMessageUid() {
return messageUid;
}
- public Date getReceivedDate() {
+ public GregorianCalendar getReceivedDate() {
return receivedDate;
}
@@ -124,7 +124,7 @@ public void setMessageUid(String messageUid) {
this.messageUid = messageUid;
}
- public void setReceivedDate(Date receivedDate) {
+ public void setReceivedDate(GregorianCalendar receivedDate) {
this.receivedDate = receivedDate;
}
@@ -178,7 +178,7 @@ public Long getGmailMsgId() {
return "MessageStatus{" +
"imapUid=" + imapUid +
", messageUid='" + messageUid + '\'' +
- ", receivedDate=" + (receivedDate == null ? "null" : ISO_C_DATE_SYDNEY.format(receivedDate)) +
+ ", receivedDate=" + (receivedDate == null ? "null" : receivedDate) +
", subject='" + subject + '\'' +
", inReplyTo='" + inReplyTo + '\'' +
", from=" + from +
View
9 sitebricks-mail/src/main/java/com/google/sitebricks/mail/imap/MessageStatusExtractor.java
@@ -1,5 +1,7 @@
package com.google.sitebricks.mail.imap;
+import com.google.sitebricks.util.*;
+
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
@@ -304,10 +306,9 @@ private static boolean parseEnvelope(Queue<String> tokens, MessageStatus status)
String receivedDate = tokens.peek();
if (Parsing.isValid(receivedDate)) {
receivedDate = Parsing.normalizeDateToken(Parsing.match(tokens, String.class));
- try {
- status.setReceivedDate(new javax.mail.internet.MailDateFormat().parse(receivedDate));
- } catch (ParseException e) {
- log.error("Malformed received date format {}. Unable to parse.", receivedDate, e);
+ status.setReceivedDate(com.google.sitebricks.util.MailDateFormat.parse(receivedDate));
+ if (status.getReceivedDate() == null) {
+ log.warning("Malformed received date format {}. Unable to parse.", receivedDate);
}
} else if (receivedDate != null) {
Parsing.eat(tokens, "NIL");
View
169 sitebricks/src/main/java/com/google/sitebricks/util/MailDateFormat.java
@@ -0,0 +1,169 @@
+package com.google.sitebricks.util;
+
+import java.io.PrintStream;
+import java.text.DecimalFormat;
+import java.text.FieldPosition;
+import java.text.NumberFormat;
+import java.text.ParsePosition;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.TimeZone;
+
+/**
+ * A modification of the GNU implementation to keep the timezone component in
+ * parsing mail date formats.
+ *
+ */
+public class MailDateFormat {
+ private static final String[] MONTHS = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+ };
+
+ /**
+ * Parses the given date in the format specified by
+ * draft-ietf-drums-msg-fmt-08 in the current TimeZone.
+ * @param text the formatted date to be parsed
+ */
+ public static GregorianCalendar parse(String text)
+ {
+ int start = 0, end = -1;
+ int len = text.length();
+ GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
+ calendar.clear();
+ ParsePosition pos = new ParsePosition(start);
+ try
+ {
+ // Advance to date
+ if (Character.isLetter(text.charAt(start)))
+ {
+ start = skipNonWhitespace(text, start, len);
+ }
+ start = skipWhitespace(text, start, len);
+ pos.setIndex(start);
+ end = skipNonWhitespace(text, start + 1, len);
+ int date = Integer.parseInt(text.substring(start, end));
+ // Advance to month
+ start = skipWhitespace(text, end + 1, len);
+ pos.setIndex(start);
+ end = skipNonWhitespace(text, start + 1, len);
+ String monthText = text.substring(start, end);
+ int month = -1;
+ for (int i = 0; i < 12; i++)
+ {
+ if (MONTHS[i].equals(monthText))
+ {
+ month = i;
+ break;
+ }
+ }
+ if (month == -1)
+ {
+ pos.setErrorIndex(end);
+ return null;
+ }
+ // Advance to year
+ start = skipWhitespace(text, end + 1, len);
+ pos.setIndex(start);
+ end = skipNonWhitespace(text, start + 1, len);
+ int year = Integer.parseInt(text.substring(start, end));
+ calendar.set(Calendar.YEAR, year);
+ calendar.set(Calendar.MONTH, month);
+ calendar.set(Calendar.DAY_OF_MONTH, date);
+ // Advance to hour
+ start = skipWhitespace(text, end + 1, len);
+ pos.setIndex(start);
+ end = skipToColon(text, start + 1, len);
+ int hour = Integer.parseInt(text.substring(start, end));
+ calendar.set(Calendar.HOUR, hour);
+ // Advance to minute
+ start = end + 1;
+ pos.setIndex(start);
+ end = skipToColon(text, start + 1, len);
+ int minute = Integer.parseInt(text.substring(start, end));
+ calendar.set(Calendar.MINUTE, minute);
+ // Advance to second
+ start = end + 1;
+ pos.setIndex(start);
+ end = skipNonWhitespace(text, start + 1, len);
+ int second = Integer.parseInt(text.substring(start, end));
+ calendar.set(Calendar.SECOND, second);
+
+ if (end != len)
+ {
+ start = skipWhitespace(text, end + 1, len);
+ if (start != len)
+ {
+ // Trailing characters, therefore timezone
+ end = skipNonWhitespace(text, start + 1, len);
+ char pm = text.charAt(start);
+ if (Character.isLetter(pm))
+ {
+ TimeZone tz =
+ TimeZone.getTimeZone(text.substring(start, end));
+ calendar.set(Calendar.ZONE_OFFSET, tz.getRawOffset());
+ }
+ else
+ {
+ int zoneOffset = 0;
+ zoneOffset +=
+ 600 * Character.digit(text.charAt(++start), 10);
+ zoneOffset +=
+ 60 * Character.digit(text.charAt(++start), 10);
+ zoneOffset +=
+ 10 * Character.digit(text.charAt(++start), 10);
+ zoneOffset +=
+ Character.digit(text.charAt(++start), 10);
+ zoneOffset *= 60000; // minutes -> ms
+ if ('-' == pm)
+ {
+ zoneOffset = -zoneOffset;
+ }
+ calendar.set(Calendar.ZONE_OFFSET, zoneOffset);
+ }
+ }
+ }
+ pos.setIndex(end);
+
+ return calendar;
+ }
+ catch (NumberFormatException e)
+ {
+ pos.setErrorIndex(Math.max(start, end));
+ }
+ catch (StringIndexOutOfBoundsException e)
+ {
+ pos.setErrorIndex(Math.max(start, end));
+ }
+ return null;
+ }
+
+ private static int skipWhitespace(final String text, int pos, final int len)
+ {
+ while (pos < len && Character.isWhitespace(text.charAt(pos)))
+ {
+ pos++;
+ }
+ return pos;
+ }
+
+ private static int skipNonWhitespace(final String text, int pos, final int len)
+ {
+ while (pos < len && !Character.isWhitespace(text.charAt(pos)))
+ {
+ pos++;
+ }
+ return pos;
+ }
+
+ private static int skipToColon(final String text, int pos, final int len)
+ {
+ while (pos < len && text.charAt(pos) != ':')
+ {
+ pos++;
+ }
+ return pos;
+ }
+}
Please sign in to comment.
Something went wrong with that request. Please try again.