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? */
|
/** @param connected are we? */
|
||||||
public void foundNewMail(boolean connected) {
|
public void foundNewMail(boolean connected) {
|
||||||
MailCache mc = null;
|
MailCache mc = null;
|
||||||
Folder<String> f = null;
|
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
Log log = _so.log;
|
Log log = _so.log;
|
||||||
if (connected) {
|
if (connected) {
|
||||||
@@ -931,7 +930,7 @@ public class WebMail extends HttpServlet
|
|||||||
if (log.shouldDebug()) log.debug("No new emails");
|
if (log.shouldDebug()) log.debug("No new emails");
|
||||||
_so.newMails = 0;
|
_so.newMails = 0;
|
||||||
_so.connectError = null;
|
_so.connectError = null;
|
||||||
} else if (mc != null && f != null) {
|
} else if (mc != null) {
|
||||||
String[] uidls = mc.getUIDLs();
|
String[] uidls = mc.getUIDLs();
|
||||||
int added = mc.getFolder().addElements(Arrays.asList(uidls));
|
int added = mc.getFolder().addElements(Arrays.asList(uidls));
|
||||||
if (added > 0)
|
if (added > 0)
|
||||||
@@ -940,7 +939,7 @@ public class WebMail extends HttpServlet
|
|||||||
_so.connectError = null;
|
_so.connectError = null;
|
||||||
if (log.shouldDebug()) log.debug("Added " + added + " new emails");
|
if (log.shouldDebug()) log.debug("Added " + added + " new emails");
|
||||||
} else {
|
} else {
|
||||||
if (log.shouldDebug()) log.debug("MailCache/folder vanished?");
|
if (log.shouldDebug()) log.debug("MailCache vanished?");
|
||||||
}
|
}
|
||||||
_mb.setNewMailListener(_so);
|
_mb.setNewMailListener(_so);
|
||||||
_so.isFetching = false;
|
_so.isFetching = false;
|
||||||
@@ -2092,7 +2091,8 @@ public class WebMail extends HttpServlet
|
|||||||
str = request.getParameter(NEW_FOLDER);
|
str = request.getParameter(NEW_FOLDER);
|
||||||
if (str == null)
|
if (str == null)
|
||||||
str = request.getParameter(CURRENT_FOLDER);
|
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;
|
q += '&' + CURRENT_FOLDER + '=' + str;
|
||||||
sendRedirect(httpRequest, response, q);
|
sendRedirect(httpRequest, response, q);
|
||||||
return;
|
return;
|
||||||
@@ -2790,7 +2790,7 @@ public class WebMail extends HttpServlet
|
|||||||
Runnable es = new EmailSender(sessionObject, draft, sender,
|
Runnable es = new EmailSender(sessionObject, draft, sender,
|
||||||
recipients.toArray(new String[recipients.size()]),
|
recipients.toArray(new String[recipients.size()]),
|
||||||
body, attachments, boundary);
|
body, attachments, boundary);
|
||||||
Thread t = new I2PAppThread(es, "Email fetcher");
|
Thread t = new I2PAppThread(es, "Email sender");
|
||||||
sessionObject.info += _t("Sending mail.") + '\n';
|
sessionObject.info += _t("Sending mail.") + '\n';
|
||||||
t.start();
|
t.start();
|
||||||
}
|
}
|
||||||
@@ -3244,6 +3244,7 @@ public class WebMail extends HttpServlet
|
|||||||
out.println(_t("Folder") + ": " + _t(name) + " "); // TODO css to center it
|
out.println(_t("Folder") + ": " + _t(name) + " "); // TODO css to center it
|
||||||
out.println(button(SWITCH_TO, _t("Change to Folder") + ':'));
|
out.println(button(SWITCH_TO, _t("Change to Folder") + ':'));
|
||||||
showFolderSelect(out, folderName, false);
|
showFolderSelect(out, folderName, false);
|
||||||
|
out.println("</td><td>");
|
||||||
if (pages > 1) {
|
if (pages > 1) {
|
||||||
if (outputHidden)
|
if (outputHidden)
|
||||||
out.println("<input type=\"hidden\" name=\"" + CUR_PAGE + "\" value=\"" + page + "\">");
|
out.println("<input type=\"hidden\" name=\"" + CUR_PAGE + "\" value=\"" + page + "\">");
|
||||||
|
@@ -92,10 +92,10 @@ class DelayedDeleter {
|
|||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
List<String> uidls = new ArrayList<String>(toDelete);
|
int origSize = toDelete.size();
|
||||||
Collection<String> deleted = mailbox.delete(uidls);
|
mailbox.deletePending(false);
|
||||||
if (_log.shouldDebug()) _log.debug("Deleted " + deleted.size() + " of " + toDelete.size() + " mails");
|
int delSize = origSize - toDelete.size();
|
||||||
toDelete.removeAll(deleted);
|
if (_log.shouldDebug()) _log.debug("Deleted " + delSize + " of " + origSize + " mails");
|
||||||
} finally {
|
} finally {
|
||||||
isDeleting = false;
|
isDeleting = false;
|
||||||
if (!isDead)
|
if (!isDead)
|
||||||
|
@@ -315,60 +315,31 @@ public class POP3MailBox implements NewMailListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete all at once and close. Does not reconnect.
|
* Delete all pending deletions at once.
|
||||||
* Do NOT call performDelete() after this.
|
* If previously connected, leaves connected.
|
||||||
* Returns all UIDLs successfully deleted OR were not known by the server.
|
* If not previously connected, closes connection when done.
|
||||||
*
|
*
|
||||||
|
* @param noWait fire-and-forget mode, only if connected
|
||||||
* @since 0.9.13
|
* @since 0.9.13
|
||||||
*/
|
*/
|
||||||
Collection<String> delete(Collection<String> uidls) {
|
void deletePending(boolean noWait) {
|
||||||
List<String> rv = new ArrayList<String>(uidls.size());
|
Collection<String> uidls = delayedDeleter.getQueued();
|
||||||
List<SendRecv> srs = new ArrayList<SendRecv>(uidls.size() + 1);
|
if (uidls.isEmpty())
|
||||||
|
return;
|
||||||
synchronized( synchronizer ) {
|
synchronized( synchronizer ) {
|
||||||
try {
|
try {
|
||||||
// we must be connected to know the UIDL to ID mapping
|
if (isConnected()) {
|
||||||
|
doDelete(noWait);
|
||||||
|
} else {
|
||||||
|
// calls connect() which calls doDelete()
|
||||||
checkConnection();
|
checkConnection();
|
||||||
} catch (IOException ioe) {
|
sendCmd1a("QUIT");
|
||||||
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) {
|
if (socket != null) {
|
||||||
try { socket.close(); } catch (IOException e) {}
|
try { socket.close(); } catch (IOException e) {}
|
||||||
socket = null;
|
socket = null;
|
||||||
connected = false;
|
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);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// why reconnect?
|
|
||||||
//connect();
|
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
if (_log.shouldDebug()) _log.debug("Error deleting", ioe);
|
if (_log.shouldDebug()) _log.debug("Error deleting", ioe);
|
||||||
if (socket != null) {
|
if (socket != null) {
|
||||||
@@ -376,10 +347,8 @@ public class POP3MailBox implements NewMailListener {
|
|||||||
socket = null;
|
socket = null;
|
||||||
connected = false;
|
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.
|
* Caller must sync.
|
||||||
* Leaves socket connected. Caller must close on IOE.
|
* Leaves socket connected. Caller must close on IOE.
|
||||||
*
|
*
|
||||||
@@ -874,10 +843,65 @@ public class POP3MailBox implements NewMailListener {
|
|||||||
updateSizes(list.ls);
|
updateSizes(list.ls);
|
||||||
else
|
else
|
||||||
if (_log.shouldDebug()) _log.debug("LIST failed");
|
if (_log.shouldDebug()) _log.debug("LIST failed");
|
||||||
|
|
||||||
|
// delete all pending deletions
|
||||||
|
doDelete(false);
|
||||||
|
|
||||||
if (socket != null) try { socket.setSoTimeout(300*1000); } catch (IOException ioe) {}
|
if (socket != null) try { socket.setSoTimeout(300*1000); } catch (IOException ioe) {}
|
||||||
return ok;
|
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)
|
* send command to pop3 server (and expect single line answer)
|
||||||
* Response will be in lastLine. Does not read past the first line of the response.
|
* Response will be in lastLine. Does not read past the first line of the response.
|
||||||
@@ -1291,33 +1315,11 @@ public class POP3MailBox implements NewMailListener {
|
|||||||
idleCloser.cancel();
|
idleCloser.cancel();
|
||||||
if (socket != null && socket.isConnected()) {
|
if (socket != null && socket.isConnected()) {
|
||||||
try {
|
try {
|
||||||
Collection<String> toDelete = delayedDeleter.getQueued();
|
deletePending(!shouldWait);
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (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");
|
if (_log.shouldDebug()) _log.debug("close() with wait complete");
|
||||||
} else {
|
} 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");
|
sendCmd1aNoWait("QUIT");
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} 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
|
2018-05-26 zzz
|
||||||
* /confignet: Reorganize (ticket #2217)
|
* /confignet: Reorganize (ticket #2217)
|
||||||
* /configsidebar: Tag sections for translation; sort unselected sections by translated name
|
* /configsidebar: Tag sections for translation; sort unselected sections by translated name
|
||||||
@@ -7,6 +13,7 @@
|
|||||||
- Hide column 1 icon for peers (ticket #1996)
|
- Hide column 1 icon for peers (ticket #1996)
|
||||||
* i2ptunnel: Retry accept after server socket closed (ticket #2003)
|
* i2ptunnel: Retry accept after server socket closed (ticket #2003)
|
||||||
* Jetty: Skip files with [] in default servlet listing
|
* 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
|
* Router: Fix wrapper.config path in OOM message when installed as
|
||||||
Debian package, but not running as a service (ticket #2223)
|
Debian package, but not running as a service (ticket #2223)
|
||||||
* Summary Bar: Change header from "I2P Updates" to "Update Status" (ticket #2137)
|
* 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);
|
filter: drop-shadow(0 0 1px #89f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
select,
|
||||||
button, input[type="submit"], input[type="reset"] {
|
button, input[type="submit"], input[type="reset"] {
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
border-radius: 2px;
|
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%);
|
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: #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%);
|
background: url(/themes/susimail/images/folder.png) no-repeat 7px center, linear-gradient(to bottom, #fff 0%, #ddd 100%);
|
||||||
padding: 5px 8px 5px 24px;
|
padding: 5px 8px 5px 24px;
|
||||||
|
@@ -514,6 +514,7 @@ input[type="text"], input[type="password"] {
|
|||||||
font-size: 9pt;
|
font-size: 9pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
select,
|
||||||
input[type="submit"], input[type="reset"] {
|
input[type="submit"], input[type="reset"] {
|
||||||
border: 1px solid #999daf;
|
border: 1px solid #999daf;
|
||||||
box-shadow: inset 0 0 0 1px #fff;
|
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);
|
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: #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);
|
background: url(/themes/susimail/images/folder.png) no-repeat 6px center, linear-gradient(to bottom, #fff, #efefff);
|
||||||
padding: 5px 7px 5px 24px;
|
padding: 5px 7px 5px 24px;
|
||||||
|
@@ -595,6 +595,7 @@ input[type=submit]::-moz-focus-inner, input.cancel::-moz-focus-inner {
|
|||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
select,
|
||||||
input[type=submit], input.cancel {
|
input[type=submit], input.cancel {
|
||||||
color: #4e47bf;
|
color: #4e47bf;
|
||||||
background: #000;
|
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;
|
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: #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;
|
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;
|
padding: 5px 7px 5px 23px !important;
|
||||||
|
@@ -18,7 +18,7 @@ public class RouterVersion {
|
|||||||
/** deprecated */
|
/** deprecated */
|
||||||
public final static String ID = "Monotone";
|
public final static String ID = "Monotone";
|
||||||
public final static String VERSION = CoreVersion.VERSION;
|
public final static String VERSION = CoreVersion.VERSION;
|
||||||
public final static long BUILD = 14;
|
public final static long BUILD = 15;
|
||||||
|
|
||||||
/** for example "-test" */
|
/** for example "-test" */
|
||||||
public final static String EXTRA = "";
|
public final static String EXTRA = "";
|
||||||
|
Reference in New Issue
Block a user