|
|
|
@ -103,7 +103,7 @@ public class ServiceSynchronize extends LifecycleService {
|
|
|
|
|
|
|
|
|
|
private static final long NOOP_INTERVAL = 9 * 60 * 1000L; // ms
|
|
|
|
|
private static final int FETCH_BATCH_SIZE = 10;
|
|
|
|
|
private static final int DOWNLOAD_BUFFER_SIZE = 8192; // bytes
|
|
|
|
|
private static final int ATTACHMENT_BUFFER_SIZE = 8192; // bytes
|
|
|
|
|
|
|
|
|
|
static final String ACTION_PROCESS_FOLDER = BuildConfig.APPLICATION_ID + ".PROCESS_FOLDER";
|
|
|
|
|
static final String ACTION_PROCESS_OUTBOX = BuildConfig.APPLICATION_ID + ".PROCESS_OUTBOX";
|
|
|
|
@ -705,10 +705,12 @@ public class ServiceSynchronize extends LifecycleService {
|
|
|
|
|
if (EntityOperation.SEEN.equals(op.name))
|
|
|
|
|
doSeen(folder, ifolder, jargs, message);
|
|
|
|
|
|
|
|
|
|
else if (EntityOperation.ADD.equals(op.name))
|
|
|
|
|
doAdd(folder, ifolder, message);
|
|
|
|
|
|
|
|
|
|
else if (EntityOperation.MOVE.equals(op.name))
|
|
|
|
|
else if (EntityOperation.ADD.equals(op.name)) {
|
|
|
|
|
List<EntityAttachment> attachments = db.attachment().getAttachments(message.id);
|
|
|
|
|
for (EntityAttachment attachment : attachments)
|
|
|
|
|
attachment.content = db.attachment().getContent(attachment.id);
|
|
|
|
|
doAdd(folder, ifolder, message, attachments);
|
|
|
|
|
} else if (EntityOperation.MOVE.equals(op.name))
|
|
|
|
|
doMove(folder, istore, ifolder, db, jargs, message);
|
|
|
|
|
|
|
|
|
|
else if (EntityOperation.DELETE.equals(op.name))
|
|
|
|
@ -774,11 +776,11 @@ public class ServiceSynchronize extends LifecycleService {
|
|
|
|
|
imessage.setFlag(Flags.Flag.SEEN, jargs.getBoolean(0));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void doAdd(EntityFolder folder, IMAPFolder ifolder, EntityMessage message) throws MessagingException {
|
|
|
|
|
private void doAdd(EntityFolder folder, IMAPFolder ifolder, EntityMessage message, List<EntityAttachment> attachments) throws MessagingException {
|
|
|
|
|
// Append message
|
|
|
|
|
Properties props = MessageHelper.getSessionProperties();
|
|
|
|
|
Session isession = Session.getInstance(props, null);
|
|
|
|
|
MimeMessage imessage = MessageHelper.from(message, isession);
|
|
|
|
|
MimeMessage imessage = MessageHelper.from(message, attachments, isession);
|
|
|
|
|
ifolder.appendMessages(new Message[]{imessage});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -825,9 +827,13 @@ public class ServiceSynchronize extends LifecycleService {
|
|
|
|
|
|
|
|
|
|
// Append copy
|
|
|
|
|
if (!EntityFolder.ARCHIVE.equals(target.type)) {
|
|
|
|
|
List<EntityAttachment> attachments = db.attachment().getAttachments(message.id);
|
|
|
|
|
for (EntityAttachment attachment : attachments)
|
|
|
|
|
attachment.content = db.attachment().getContent(attachment.id);
|
|
|
|
|
|
|
|
|
|
Properties props = MessageHelper.getSessionProperties();
|
|
|
|
|
Session isession = Session.getInstance(props, null);
|
|
|
|
|
MimeMessage icopy = MessageHelper.from(message, isession);
|
|
|
|
|
MimeMessage icopy = MessageHelper.from(message, attachments, isession);
|
|
|
|
|
itarget.appendMessages(new Message[]{icopy});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -856,51 +862,54 @@ public class ServiceSynchronize extends LifecycleService {
|
|
|
|
|
|
|
|
|
|
private void doSend(DB db, EntityMessage message) throws MessagingException {
|
|
|
|
|
// Send message
|
|
|
|
|
EntityMessage reply = (message.replying == null ? null : db.message().getMessage(message.replying));
|
|
|
|
|
EntityIdentity ident = db.identity().getIdentity(message.identity);
|
|
|
|
|
EntityMessage reply = (message.replying == null ? null : db.message().getMessage(message.replying));
|
|
|
|
|
List<EntityAttachment> attachments = db.attachment().getAttachments(message.id);
|
|
|
|
|
for (EntityAttachment attachment : attachments)
|
|
|
|
|
attachment.content = db.attachment().getContent(attachment.id);
|
|
|
|
|
|
|
|
|
|
if (!ident.synchronize) {
|
|
|
|
|
// Message will remain in outbox
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
db.beginTransaction();
|
|
|
|
|
// Create session
|
|
|
|
|
Properties props = MessageHelper.getSessionProperties();
|
|
|
|
|
Session isession = Session.getInstance(props, null);
|
|
|
|
|
|
|
|
|
|
// Move message to sent
|
|
|
|
|
EntityFolder sent = db.folder().getFolderByType(ident.account, EntityFolder.SENT);
|
|
|
|
|
if (sent == null)
|
|
|
|
|
; // Leave message in outbox
|
|
|
|
|
else {
|
|
|
|
|
message.folder = sent.id;
|
|
|
|
|
message.uid = null;
|
|
|
|
|
}
|
|
|
|
|
// Create message
|
|
|
|
|
MimeMessage imessage;
|
|
|
|
|
if (reply == null)
|
|
|
|
|
imessage = MessageHelper.from(message, attachments, isession);
|
|
|
|
|
else
|
|
|
|
|
imessage = MessageHelper.from(message, reply, attachments, isession);
|
|
|
|
|
if (ident.replyto != null)
|
|
|
|
|
imessage.setReplyTo(new Address[]{new InternetAddress(ident.replyto)});
|
|
|
|
|
|
|
|
|
|
// Create session
|
|
|
|
|
Properties props = MessageHelper.getSessionProperties();
|
|
|
|
|
Session isession = Session.getInstance(props, null);
|
|
|
|
|
// Create transport
|
|
|
|
|
// TODO: cache transport?
|
|
|
|
|
Transport itransport = isession.getTransport(ident.starttls ? "smtp" : "smtps");
|
|
|
|
|
try {
|
|
|
|
|
// Connect transport
|
|
|
|
|
itransport.connect(ident.host, ident.port, ident.user, ident.password);
|
|
|
|
|
|
|
|
|
|
// Create message
|
|
|
|
|
MimeMessage imessage;
|
|
|
|
|
if (reply == null)
|
|
|
|
|
imessage = MessageHelper.from(message, isession);
|
|
|
|
|
else
|
|
|
|
|
imessage = MessageHelper.from(message, reply, isession);
|
|
|
|
|
if (ident.replyto != null)
|
|
|
|
|
imessage.setReplyTo(new Address[]{new InternetAddress(ident.replyto)});
|
|
|
|
|
|
|
|
|
|
// Create transport
|
|
|
|
|
// TODO: cache transport?
|
|
|
|
|
Transport itransport = isession.getTransport(ident.starttls ? "smtp" : "smtps");
|
|
|
|
|
try {
|
|
|
|
|
// Connect transport
|
|
|
|
|
itransport.connect(ident.host, ident.port, ident.user, ident.password);
|
|
|
|
|
// Send message
|
|
|
|
|
Address[] to = imessage.getAllRecipients();
|
|
|
|
|
itransport.sendMessage(imessage, to);
|
|
|
|
|
Log.i(Helper.TAG, "Sent via " + ident.host + "/" + ident.user +
|
|
|
|
|
" to " + TextUtils.join(", ", to));
|
|
|
|
|
|
|
|
|
|
// Send message
|
|
|
|
|
Address[] to = imessage.getAllRecipients();
|
|
|
|
|
itransport.sendMessage(imessage, to);
|
|
|
|
|
Log.i(Helper.TAG, "Sent via " + ident.host + "/" + ident.user +
|
|
|
|
|
" to " + TextUtils.join(", ", to));
|
|
|
|
|
try {
|
|
|
|
|
db.beginTransaction();
|
|
|
|
|
|
|
|
|
|
// Move message to sent
|
|
|
|
|
EntityFolder sent = db.folder().getFolderByType(ident.account, EntityFolder.SENT);
|
|
|
|
|
if (sent == null)
|
|
|
|
|
; // Leave message in outbox
|
|
|
|
|
else {
|
|
|
|
|
message.folder = sent.id;
|
|
|
|
|
message.uid = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update state
|
|
|
|
|
if (message.thread == null)
|
|
|
|
@ -913,13 +922,12 @@ public class ServiceSynchronize extends LifecycleService {
|
|
|
|
|
if (sent != null)
|
|
|
|
|
EntityOperation.queue(db, message, EntityOperation.ADD); // Could already exist
|
|
|
|
|
|
|
|
|
|
db.setTransactionSuccessful();
|
|
|
|
|
} finally {
|
|
|
|
|
itransport.close();
|
|
|
|
|
db.endTransaction();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
db.setTransactionSuccessful();
|
|
|
|
|
} finally {
|
|
|
|
|
db.endTransaction();
|
|
|
|
|
itransport.close();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -943,7 +951,7 @@ public class ServiceSynchronize extends LifecycleService {
|
|
|
|
|
// Download attachment
|
|
|
|
|
InputStream is = a.part.getInputStream();
|
|
|
|
|
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
|
|
|
|
byte[] buffer = new byte[DOWNLOAD_BUFFER_SIZE];
|
|
|
|
|
byte[] buffer = new byte[ATTACHMENT_BUFFER_SIZE];
|
|
|
|
|
for (int len = is.read(buffer); len != -1; len = is.read(buffer)) {
|
|
|
|
|
os.write(buffer, 0, len);
|
|
|
|
|
|
|
|
|
|