forked from I2P_Developers/i2p.i2p
SusiMail: Send deletions after connect so emails don't come back after a move (ticket #2087)
Refactor/consolidate pop3 deletion code Fix loading mails in checker Fix checker thread name Return to inbox, not drafts, after sending draft CSS for select
This commit is contained in:
@@ -893,7 +893,6 @@ public class WebMail extends HttpServlet
|
||||
/** @param connected are we? */
|
||||
public void foundNewMail(boolean connected) {
|
||||
MailCache mc = null;
|
||||
Folder<String> f = null;
|
||||
boolean found = false;
|
||||
Log log = _so.log;
|
||||
if (connected) {
|
||||
@@ -931,7 +930,7 @@ public class WebMail extends HttpServlet
|
||||
if (log.shouldDebug()) log.debug("No new emails");
|
||||
_so.newMails = 0;
|
||||
_so.connectError = null;
|
||||
} else if (mc != null && f != null) {
|
||||
} else if (mc != null) {
|
||||
String[] uidls = mc.getUIDLs();
|
||||
int added = mc.getFolder().addElements(Arrays.asList(uidls));
|
||||
if (added > 0)
|
||||
@@ -940,7 +939,7 @@ public class WebMail extends HttpServlet
|
||||
_so.connectError = null;
|
||||
if (log.shouldDebug()) log.debug("Added " + added + " new emails");
|
||||
} else {
|
||||
if (log.shouldDebug()) log.debug("MailCache/folder vanished?");
|
||||
if (log.shouldDebug()) log.debug("MailCache vanished?");
|
||||
}
|
||||
_mb.setNewMailListener(_so);
|
||||
_so.isFetching = false;
|
||||
@@ -2092,7 +2091,8 @@ public class WebMail extends HttpServlet
|
||||
str = request.getParameter(NEW_FOLDER);
|
||||
if (str == null)
|
||||
str = request.getParameter(CURRENT_FOLDER);
|
||||
if (str != null && !str.equals(DIR_FOLDER))
|
||||
// always go to inbox after SEND
|
||||
if (str != null && !str.equals(DIR_FOLDER) && !buttonPressed(request, SEND))
|
||||
q += '&' + CURRENT_FOLDER + '=' + str;
|
||||
sendRedirect(httpRequest, response, q);
|
||||
return;
|
||||
@@ -2790,7 +2790,7 @@ public class WebMail extends HttpServlet
|
||||
Runnable es = new EmailSender(sessionObject, draft, sender,
|
||||
recipients.toArray(new String[recipients.size()]),
|
||||
body, attachments, boundary);
|
||||
Thread t = new I2PAppThread(es, "Email fetcher");
|
||||
Thread t = new I2PAppThread(es, "Email sender");
|
||||
sessionObject.info += _t("Sending mail.") + '\n';
|
||||
t.start();
|
||||
}
|
||||
@@ -3244,6 +3244,7 @@ public class WebMail extends HttpServlet
|
||||
out.println(_t("Folder") + ": " + _t(name) + " "); // TODO css to center it
|
||||
out.println(button(SWITCH_TO, _t("Change to Folder") + ':'));
|
||||
showFolderSelect(out, folderName, false);
|
||||
out.println("</td><td>");
|
||||
if (pages > 1) {
|
||||
if (outputHidden)
|
||||
out.println("<input type=\"hidden\" name=\"" + CUR_PAGE + "\" value=\"" + page + "\">");
|
||||
|
@@ -92,10 +92,10 @@ class DelayedDeleter {
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
List<String> uidls = new ArrayList<String>(toDelete);
|
||||
Collection<String> deleted = mailbox.delete(uidls);
|
||||
if (_log.shouldDebug()) _log.debug("Deleted " + deleted.size() + " of " + toDelete.size() + " mails");
|
||||
toDelete.removeAll(deleted);
|
||||
int origSize = toDelete.size();
|
||||
mailbox.deletePending(false);
|
||||
int delSize = origSize - toDelete.size();
|
||||
if (_log.shouldDebug()) _log.debug("Deleted " + delSize + " of " + origSize + " mails");
|
||||
} finally {
|
||||
isDeleting = false;
|
||||
if (!isDead)
|
||||
|
@@ -315,60 +315,31 @@ public class POP3MailBox implements NewMailListener {
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all at once and close. Does not reconnect.
|
||||
* Do NOT call performDelete() after this.
|
||||
* Returns all UIDLs successfully deleted OR were not known by the server.
|
||||
* Delete all pending deletions at once.
|
||||
* If previously connected, leaves connected.
|
||||
* If not previously connected, closes connection when done.
|
||||
*
|
||||
* @param noWait fire-and-forget mode, only if connected
|
||||
* @since 0.9.13
|
||||
*/
|
||||
Collection<String> delete(Collection<String> uidls) {
|
||||
List<String> rv = new ArrayList<String>(uidls.size());
|
||||
List<SendRecv> srs = new ArrayList<SendRecv>(uidls.size() + 1);
|
||||
void deletePending(boolean noWait) {
|
||||
Collection<String> uidls = delayedDeleter.getQueued();
|
||||
if (uidls.isEmpty())
|
||||
return;
|
||||
synchronized( synchronizer ) {
|
||||
try {
|
||||
// we must be connected to know the UIDL to ID mapping
|
||||
checkConnection();
|
||||
} catch (IOException ioe) {
|
||||
if (_log.shouldDebug()) _log.debug("Error deleting", ioe);
|
||||
return rv;
|
||||
}
|
||||
for (String uidl : uidls) {
|
||||
int id = getIDfromUIDL(uidl);
|
||||
if (id < 0) {
|
||||
// presumed already deleted
|
||||
rv.add(uidl);
|
||||
continue;
|
||||
}
|
||||
SendRecv sr = new SendRecv("DELE " + id, Mode.A1);
|
||||
sr.savedObject = uidl;
|
||||
srs.add(sr);
|
||||
}
|
||||
if (srs.isEmpty())
|
||||
return rv;
|
||||
// TODO don't quit now, just set timer to quit later
|
||||
SendRecv quit = new SendRecv("QUIT", Mode.A1);
|
||||
srs.add(quit);
|
||||
try {
|
||||
sendCmds(srs);
|
||||
// do NOT call close() here, we included QUIT above
|
||||
if (socket != null) {
|
||||
try { socket.close(); } catch (IOException e) {}
|
||||
socket = null;
|
||||
connected = false;
|
||||
}
|
||||
clear();
|
||||
// result of QUIT
|
||||
boolean success = srs.get(srs.size() - 1).result;
|
||||
if (success) {
|
||||
for (int i = 0; i < srs.size() - 1; i++) {
|
||||
SendRecv sr = srs.get(i);
|
||||
// ignore sr.result, if it failed it's because
|
||||
// it's already deleted
|
||||
rv.add((String) sr.savedObject);
|
||||
if (isConnected()) {
|
||||
doDelete(noWait);
|
||||
} else {
|
||||
// calls connect() which calls doDelete()
|
||||
checkConnection();
|
||||
sendCmd1a("QUIT");
|
||||
if (socket != null) {
|
||||
try { socket.close(); } catch (IOException e) {}
|
||||
socket = null;
|
||||
connected = false;
|
||||
}
|
||||
}
|
||||
// why reconnect?
|
||||
//connect();
|
||||
} catch (IOException ioe) {
|
||||
if (_log.shouldDebug()) _log.debug("Error deleting", ioe);
|
||||
if (socket != null) {
|
||||
@@ -376,10 +347,8 @@ public class POP3MailBox implements NewMailListener {
|
||||
socket = null;
|
||||
connected = false;
|
||||
}
|
||||
// todo maybe
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -841,7 +810,7 @@ public class POP3MailBox implements NewMailListener {
|
||||
}
|
||||
|
||||
/**
|
||||
* Send STAT, UIDL, LIST. Must be connected.
|
||||
* Send STAT, UIDL, LIST, and DELE for all pending. Must be connected.
|
||||
* Caller must sync.
|
||||
* Leaves socket connected. Caller must close on IOE.
|
||||
*
|
||||
@@ -874,9 +843,64 @@ public class POP3MailBox implements NewMailListener {
|
||||
updateSizes(list.ls);
|
||||
else
|
||||
if (_log.shouldDebug()) _log.debug("LIST failed");
|
||||
|
||||
// delete all pending deletions
|
||||
doDelete(false);
|
||||
|
||||
if (socket != null) try { socket.setSoTimeout(300*1000); } catch (IOException ioe) {}
|
||||
return ok;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send DELE for all pending deletions. Must be connected.
|
||||
* Caller must sync.
|
||||
* Leaves socket connected. Caller must close on IOE.
|
||||
*
|
||||
* @param noWait fire-and-forget mode
|
||||
* @throws IOException
|
||||
* @since 0.9.35 pulled out of delete()
|
||||
*/
|
||||
private void doDelete(boolean noWait) throws IOException {
|
||||
// delete all pending deletions
|
||||
Collection<String> uidls = delayedDeleter.getQueued();
|
||||
if (uidls.isEmpty())
|
||||
return;
|
||||
List<SendRecv> cmds = new ArrayList<SendRecv>(uidls.size());
|
||||
for (String uid : uidls) {
|
||||
int id = getIDfromUIDL(uid);
|
||||
if (id < 0) {
|
||||
// presumed already deleted
|
||||
delayedDeleter.removeQueued(uid);
|
||||
continue;
|
||||
}
|
||||
if (noWait) {
|
||||
sendCmd1aNoWait("DELE " + id);
|
||||
delayedDeleter.removeQueued(uid);
|
||||
uidlToID.remove(uid);
|
||||
sizes.remove(Integer.valueOf(id));
|
||||
} else {
|
||||
SendRecv sr = new SendRecv("DELE " + id, Mode.A1);
|
||||
sr.savedObject = uid;
|
||||
cmds.add(sr);
|
||||
}
|
||||
}
|
||||
if (!cmds.isEmpty()) {
|
||||
// ignore rv
|
||||
sendCmds(cmds);
|
||||
// use isConnected() as a proxy for success
|
||||
if (isConnected()) {
|
||||
for (SendRecv sr : cmds) {
|
||||
// ignore sr.result, if it failed it's because
|
||||
// it's already deleted
|
||||
String uid = (String) sr.savedObject;
|
||||
delayedDeleter.removeQueued(uid);
|
||||
Integer id = uidlToID.remove(uid);
|
||||
if (id != null)
|
||||
sizes.remove(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* send command to pop3 server (and expect single line answer)
|
||||
@@ -1291,33 +1315,11 @@ public class POP3MailBox implements NewMailListener {
|
||||
idleCloser.cancel();
|
||||
if (socket != null && socket.isConnected()) {
|
||||
try {
|
||||
Collection<String> toDelete = delayedDeleter.getQueued();
|
||||
Map<String, Integer> sendDelete = new HashMap<String, Integer>(toDelete.size());
|
||||
for (String uidl : toDelete) {
|
||||
int id = getIDfromUIDL(uidl);
|
||||
if (id >= 0) {
|
||||
sendDelete.put(uidl, Integer.valueOf(id));
|
||||
}
|
||||
}
|
||||
deletePending(!shouldWait);
|
||||
if (shouldWait) {
|
||||
if (!sendDelete.isEmpty()) {
|
||||
// Verify deleted, remove from the delete queue
|
||||
// this does the quit and close
|
||||
Collection<String> deleted = delete(sendDelete.keySet());
|
||||
for (String uidl : deleted) {
|
||||
delayedDeleter.removeQueued(uidl);
|
||||
}
|
||||
} else {
|
||||
sendCmd1a("QUIT");
|
||||
}
|
||||
sendCmd1a("QUIT");
|
||||
if (_log.shouldDebug()) _log.debug("close() with wait complete");
|
||||
} else {
|
||||
if (!sendDelete.isEmpty()) {
|
||||
// spray and pray the deletions, don't remove from delete queue
|
||||
for (Integer id : sendDelete.values()) {
|
||||
sendCmd1aNoWait("DELE " + id);
|
||||
}
|
||||
}
|
||||
sendCmd1aNoWait("QUIT");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
|
@@ -1,3 +1,9 @@
|
||||
2018-05-28 zzz
|
||||
* SusiMail: (ticket #2087)
|
||||
- Send deletions after connect so emails don't come back after a move
|
||||
- Fix fetches in check mail
|
||||
- CSS fixes
|
||||
|
||||
2018-05-26 zzz
|
||||
* /confignet: Reorganize (ticket #2217)
|
||||
* /configsidebar: Tag sections for translation; sort unselected sections by translated name
|
||||
@@ -7,6 +13,7 @@
|
||||
- Hide column 1 icon for peers (ticket #1996)
|
||||
* i2ptunnel: Retry accept after server socket closed (ticket #2003)
|
||||
* Jetty: Skip files with [] in default servlet listing
|
||||
* ministreaming: Add classpath to jar (ticket #2228)
|
||||
* Router: Fix wrapper.config path in OOM message when installed as
|
||||
Debian package, but not running as a service (ticket #2223)
|
||||
* Summary Bar: Change header from "I2P Updates" to "Update Status" (ticket #2137)
|
||||
|
@@ -509,6 +509,7 @@ button:focus, input[type="submit"]:focus, input[type="reset"]:focus {
|
||||
filter: drop-shadow(0 0 1px #89f);
|
||||
}
|
||||
|
||||
select,
|
||||
button, input[type="submit"], input[type="reset"] {
|
||||
padding: 5px;
|
||||
border-radius: 2px;
|
||||
@@ -630,7 +631,7 @@ input.offline:hover, input.offline:focus {
|
||||
background: url(/themes/susimail/images/offline_hover.png) no-repeat 7px center, linear-gradient(to bottom, #ddd 0%, #fff 100%);
|
||||
}
|
||||
|
||||
input.list, input.moveto, input.switchto {
|
||||
input.list, input.moveto, #pagenav input.switchto {
|
||||
background: #eee url(/themes/susimail/images/folder.png) no-repeat 7px center;
|
||||
background: url(/themes/susimail/images/folder.png) no-repeat 7px center, linear-gradient(to bottom, #fff 0%, #ddd 100%);
|
||||
padding: 5px 8px 5px 24px;
|
||||
|
@@ -514,6 +514,7 @@ input[type="text"], input[type="password"] {
|
||||
font-size: 9pt;
|
||||
}
|
||||
|
||||
select,
|
||||
input[type="submit"], input[type="reset"] {
|
||||
border: 1px solid #999daf;
|
||||
box-shadow: inset 0 0 0 1px #fff;
|
||||
@@ -607,7 +608,7 @@ input.offline:hover {
|
||||
background: url(/themes/susimail/images/offline_hover.png) no-repeat 6px center, linear-gradient(to bottom, #eee, #fff);
|
||||
}
|
||||
|
||||
input.list, input.moveto, input.switchto {
|
||||
input.list, input.moveto, #pagenav input.switchto {
|
||||
background: #eee url(/themes/susimail/images/folder.png) no-repeat 6px center;
|
||||
background: url(/themes/susimail/images/folder.png) no-repeat 6px center, linear-gradient(to bottom, #fff, #efefff);
|
||||
padding: 5px 7px 5px 24px;
|
||||
|
@@ -595,6 +595,7 @@ input[type=submit]::-moz-focus-inner, input.cancel::-moz-focus-inner {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
select,
|
||||
input[type=submit], input.cancel {
|
||||
color: #4e47bf;
|
||||
background: #000;
|
||||
@@ -1071,7 +1072,7 @@ input.offline:hover, input.offline:focus {
|
||||
background: #000 url(/themes/susimail/images/offline_hover.png) no-repeat 6px center !important;
|
||||
}
|
||||
|
||||
input.list, input.moveto, input.switchto {
|
||||
input.list, input.moveto, #pagenav input.switchto {
|
||||
background: #000 url(/themes/susimail/images/folder.png) no-repeat 6px center !important;
|
||||
background: url(/themes/susimail/images/folder.png) no-repeat 6px center, linear-gradient(to bottom, #1f1e32, #090812 50%, #000 50%) !important;
|
||||
padding: 5px 7px 5px 23px !important;
|
||||
|
@@ -18,7 +18,7 @@ public class RouterVersion {
|
||||
/** deprecated */
|
||||
public final static String ID = "Monotone";
|
||||
public final static String VERSION = CoreVersion.VERSION;
|
||||
public final static long BUILD = 14;
|
||||
public final static long BUILD = 15;
|
||||
|
||||
/** for example "-test" */
|
||||
public final static String EXTRA = "";
|
||||
|
Reference in New Issue
Block a user