Attempt to fix several flaws that prevented me from backing up my 650MB of mails from my BeOS partition:
- Select() didn't actually reselect even when asked to force things from AddMessage(), making the uploaded mail get an off-by-one unique id assigned and a second copy downloaded on subsequent fetching, though this would really need proofreading as I'm not really sure how it all works, - the allocated buffer wasn't freed, making mail_daemon allocate 650MB, which obviously crashed when out of physical ram, now it only uses 15MB :p, - try to find workable IMAP flags for sent and pending mails, or use custom ones when the server allows arbitrary flags, - the LIST command wasn't checked for correct response, making subsequent commands like CREATE mailbox fail from the OK answer of previous ones when syncing on a new accound, - try to read the creating time (actually modification time since creation time is reset when copying files around) and pass it to APPEND command so I won't get the whole 10000 mails all received as of today. Now I can put all my old mails on an imap server (tested on dovecot) to read it from other OSes. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36995 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
a5bc5bb66d
commit
0c538753e2
@ -114,6 +114,8 @@ class IMAP4Client : public BRemoteMailStorageProtocol {
|
||||
bool force_reselect;
|
||||
|
||||
int32 fLastExists;
|
||||
BString fSentFlag;
|
||||
BString fPendingFlag;
|
||||
};
|
||||
|
||||
class NoopWorker : public BHandler {
|
||||
@ -386,6 +388,7 @@ void IMAP4Client::InitializeMailboxes() {
|
||||
hierarchy_delimiter = dem[2]();
|
||||
if (hierarchy_delimiter == "" || hierarchy_delimiter == "NIL")
|
||||
hierarchy_delimiter = "/";
|
||||
WasCommandOkay(tag);
|
||||
}
|
||||
|
||||
if (mb_root.ByteAt(mb_root.Length() - 1) != hierarchy_delimiter.ByteAt(0)) {
|
||||
@ -433,17 +436,33 @@ status_t IMAP4Client::AddMessage(const char *mailbox, BPositionIO *data, BString
|
||||
if (node != NULL) {
|
||||
BString status;
|
||||
node->ReadAttrString(B_MAIL_ATTR_STATUS,&status);
|
||||
/*if (status == "Sent")
|
||||
attributes += " \\Sent";
|
||||
if (status == "Pending")
|
||||
attributes += " \\Sent";*/
|
||||
if (status == "Sent" && fSentFlag.Length())
|
||||
attributes << " " << fSentFlag;
|
||||
if (status == "Pending" && fPendingFlag.Length())
|
||||
attributes << " " << fPendingFlag;
|
||||
if (status == "Replied")
|
||||
attributes += " \\Answered";
|
||||
}
|
||||
}
|
||||
|
||||
BString receivedDate;
|
||||
BFile *file = dynamic_cast<BFile *> (data);
|
||||
time_t creationTime;
|
||||
// actually creation time is reset on file copy, modification time seems better...
|
||||
if (file && file->GetModificationTime(&creationTime) == B_OK) {
|
||||
struct tm tm;
|
||||
localtime_r(&creationTime, &tm);
|
||||
char *buffer = receivedDate.LockBuffer(256);
|
||||
|
||||
command << ((struct mailbox_info *)(box_info.ItemAt(box_index)))->server_mb_name << "\" (" << attributes << ") {" << size << '}';
|
||||
strftime(buffer, 256, "%e-%b-%Y %H:%M:%S %z", &tm);
|
||||
receivedDate.UnlockBuffer();
|
||||
receivedDate.Prepend('"', 1);
|
||||
receivedDate << "\" ";
|
||||
}
|
||||
|
||||
|
||||
command << ((struct mailbox_info *)(box_info.ItemAt(box_index)))->server_mb_name
|
||||
<< "\" (" << attributes << ") " << receivedDate << "{" << size << '}';
|
||||
SendCommand(command.String());
|
||||
status_t err = ReceiveLine(command);
|
||||
if (err < B_OK)
|
||||
@ -461,7 +480,10 @@ status_t IMAP4Client::AddMessage(const char *mailbox, BPositionIO *data, BString
|
||||
send(net,buffer,size,0);
|
||||
send(net,"\r\n",2,0);
|
||||
}
|
||||
Select(mailbox,false,false,false,true);
|
||||
delete [] buffer;
|
||||
|
||||
force_reselect = true;
|
||||
Select(mailbox,true,false,false,false,false);
|
||||
|
||||
if (((struct mailbox_info *)(box_info.ItemAt(box_index)))->next_uid <= 0) {
|
||||
command = "FETCH ";
|
||||
@ -679,7 +701,7 @@ status_t IMAP4Client::Select(const char *mb, bool reselect, bool queue_new_messa
|
||||
|
||||
const char *real_mb = info->server_mb_name.String();
|
||||
|
||||
if ((selected_mb != real_mb) || (noop) || (no_command)) {
|
||||
if ((selected_mb != real_mb) || (noop) || (no_command) || (reselect)) {
|
||||
if ((selected_mb != "") && (selected_mb != real_mb)){
|
||||
BString trash;
|
||||
if (SendCommand("CLOSE") < B_OK)
|
||||
@ -689,7 +711,7 @@ status_t IMAP4Client::Select(const char *mb, bool reselect, bool queue_new_messa
|
||||
WasCommandOkay(trash);
|
||||
}
|
||||
BString cmd;
|
||||
if (selected_mb == real_mb)
|
||||
if (selected_mb == real_mb && !reselect)
|
||||
cmd = "NOOP";
|
||||
else
|
||||
cmd << "SELECT \"" << real_mb << '\"';
|
||||
@ -720,6 +742,32 @@ status_t IMAP4Client::Select(const char *mb, bool reselect, bool queue_new_messa
|
||||
|
||||
if ((response.CountItems() > 1) && (strcasecmp(response[1](),"RECENT") == 0))
|
||||
recent = atoi(response[0]());
|
||||
|
||||
// search a workable Sent flag.
|
||||
// cf.
|
||||
// http://serverfault.com/questions/115769/which-imap-flags-are-reliably-supported-across-most-mail-servers
|
||||
if (response[0].CountItems() == 2 && strcasecmp(response[0][0](),"PERMANENTFLAGS") == 0) {
|
||||
//PRINT(("PERM FLAGS: '%s'\n", response[0][1]()));
|
||||
for (int i = 0; i < response[0][1].CountItems(); i++) {
|
||||
BString flag(response[0][1][i]());
|
||||
//PRINT(("PERM FLAGS[%d]: '%s'\n", i, response[0][1][i]()));
|
||||
// lucky you
|
||||
if (flag == "\\Sent")
|
||||
fSentFlag = "\\Sent";
|
||||
// the server supports arbitrary flags, define our own;
|
||||
else if (flag == "\\*")
|
||||
fSentFlag = "$Sent";
|
||||
// note $MDNSent is not the same, it's used for delivery notifications...
|
||||
|
||||
if (flag == "\\Pending")
|
||||
fPendingFlag = "\\Pending";
|
||||
// the server supports arbitrary flags, define our own;
|
||||
else if (flag == "\\*")
|
||||
fPendingFlag = "$Pending";
|
||||
}
|
||||
//PRINT(("Sent FLAG: '%s'\n", fSentFlag.String()));
|
||||
//PRINT(("Pending FLAG: '%s'\n", fPendingFlag.String()));
|
||||
}
|
||||
}
|
||||
|
||||
// Whenever the mailbox is updated, only EXISTS is sent so we have no
|
||||
@ -871,12 +919,18 @@ status_t IMAP4Client::GetMessage(const char *mailbox, const char *message, BPosi
|
||||
if (strcmp(response[2][1][i](),"\\Seen") == 0) {
|
||||
headers->AddString("STATUS","Read");
|
||||
}
|
||||
if (strcmp(response[2][1][i](),"\\Sent") == 0) {
|
||||
if (fSentFlag.Length() && strcmp(response[2][1][i](),fSentFlag.String()) == 0) {
|
||||
if (headers->HasString("STATUS"))
|
||||
headers->ReplaceString("STATUS","Sent");
|
||||
else
|
||||
headers->AddString("STATUS","Sent");
|
||||
}
|
||||
if (fPendingFlag.Length() && strcmp(response[2][1][i](),fPendingFlag.String()) == 0) {
|
||||
if (headers->HasString("STATUS"))
|
||||
headers->ReplaceString("STATUS","Pending");
|
||||
else
|
||||
headers->AddString("STATUS","Pending");
|
||||
}
|
||||
if (strcmp(response[2][1][i](),"\\Answered") == 0) {
|
||||
if (headers->HasString("STATUS"))
|
||||
headers->ReplaceString("STATUS","Replied");
|
||||
|
Loading…
Reference in New Issue
Block a user