diff --git a/headers/os/add-ons/mail_daemon/MailProtocol.h b/headers/os/add-ons/mail_daemon/MailProtocol.h index 31a8baa5bb..3b558dd34e 100644 --- a/headers/os/add-ons/mail_daemon/MailProtocol.h +++ b/headers/os/add-ons/mail_daemon/MailProtocol.h @@ -17,6 +17,7 @@ #include #include +#include #include @@ -145,7 +146,7 @@ public: virtual status_t SyncMessages() = 0; virtual status_t FetchBody(const entry_ref& ref) = 0; virtual status_t MarkMessageAsRead(const entry_ref& ref, - bool read = true); + read_flags flag = B_READ); virtual status_t DeleteMessage(const entry_ref& ref) = 0; virtual status_t AppendMessage(const entry_ref& ref); }; @@ -196,7 +197,7 @@ public: void FetchBody(const entry_ref& ref, BMessage* launch = NULL); void MarkMessageAsRead(const entry_ref& ref, - bool read = true); + read_flags flag = B_READ); void DeleteMessage(const entry_ref& ref); void AppendMessage(const entry_ref& ref); private: diff --git a/headers/os/mail/E-mail.h b/headers/os/mail/E-mail.h index bfac0c1499..72662586c4 100644 --- a/headers/os/mail/E-mail.h +++ b/headers/os/mail/E-mail.h @@ -28,6 +28,16 @@ struct entry_ref; #define B_MAIL_ATTR_MIME "MAIL:mime" // string #define B_MAIL_ATTR_HEADER "MAIL:header_length" // int32 #define B_MAIL_ATTR_CONTENT "MAIL:content_length" // int32 +#define B_MAIL_ATTR_READ "MAIL:read" // int32 + + +// read flags +enum read_flags { + B_UNREAD = 0, + B_SEEN = 1, + B_READ = 2 + +}; // mail flags diff --git a/headers/os/mail/MailDaemon.h b/headers/os/mail/MailDaemon.h index 43b26431a1..bb394ccdb8 100644 --- a/headers/os/mail/MailDaemon.h +++ b/headers/os/mail/MailDaemon.h @@ -7,6 +7,9 @@ */ +#include + + const uint32 kMsgCheckAndSend = 'mbth'; const uint32 kMsgCheckMessage = 'mnow'; const uint32 kMsgSendMessages = 'msnd'; @@ -27,7 +30,7 @@ public: static int32 CountNewMessages( bool waitForFetchCompletion = false); static status_t MarkAsRead(int32 account, const entry_ref& ref, - bool read = true); + read_flags flag = B_READ); static status_t FetchBody(const entry_ref& ref, BMessage* launchMessage = NULL); static status_t Quit(); diff --git a/headers/os/mail/MailSettings.h b/headers/os/mail/MailSettings.h index 443f1601da..29eb5a3e24 100644 --- a/headers/os/mail/MailSettings.h +++ b/headers/os/mail/MailSettings.h @@ -39,7 +39,7 @@ typedef enum } b_mail_status_window_look; -#define kDefaultSentDirectory "/boot/home/mail/sent" +BString default_sent_directory(); class BMailSettings { diff --git a/headers/private/mail/mail_util.h b/headers/private/mail/mail_util.h index a20981167a..df94e1a006 100644 --- a/headers/private/mail/mail_util.h +++ b/headers/private/mail/mail_util.h @@ -8,8 +8,17 @@ #include +#include + +#include + + class BString; + +status_t write_read_attr(BNode& node, read_flags flag); + + // The next couple of functions are our wrapper around convert_to_utf8 and // convert_from_utf8 so that they can also convert from UTF-8 to UTF-8 by // specifying the MDR_UTF8_CONVERSION constant as the conversion operation. diff --git a/src/add-ons/mail_daemon/inbound_filters/match_header/RuleFilter.cpp b/src/add-ons/mail_daemon/inbound_filters/match_header/RuleFilter.cpp index bcb3123334..2410d9aa18 100644 --- a/src/add-ons/mail_daemon/inbound_filters/match_header/RuleFilter.cpp +++ b/src/add-ons/mail_daemon/inbound_filters/match_header/RuleFilter.cpp @@ -89,7 +89,7 @@ RuleFilter::HeaderFetched(const entry_ref& ref, BFile* file) case Z_SET_READ: { InboundProtocol& protocol = (InboundProtocol&)fMailProtocol; - protocol.MarkMessageAsRead(ref, true); + protocol.MarkMessageAsRead(ref, B_READ); break; } default: diff --git a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPInboundProtocol.cpp b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPInboundProtocol.cpp index 63e914fc5c..84718f4f8f 100644 --- a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPInboundProtocol.cpp +++ b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPInboundProtocol.cpp @@ -484,7 +484,7 @@ IMAPInboundProtocol::FetchBody(const entry_ref& ref) status_t -IMAPInboundProtocol::MarkMessageAsRead(const entry_ref& ref, bool read) +IMAPInboundProtocol::MarkMessageAsRead(const entry_ref& ref, read_flags flag) { if (!IsConnected()) Connect(fServer, fUsername, fPassword, fUseSSL); @@ -492,14 +492,16 @@ IMAPInboundProtocol::MarkMessageAsRead(const entry_ref& ref, bool read) fIMAPMailboxThread->StopWatchingMailbox(); int32 uid = fStorage.RefToUID(ref); int32 flags = fStorage.GetFlags(uid); - if (read) + if (flag == B_READ) flags |= kSeen; else flags &= ~kSeen; status_t status = fIMAPMailbox.SetFlags( fIMAPMailbox.UIDToMessageNumber(uid), flags); fIMAPMailboxThread->SyncAndStartWatchingMailbox(); - return status; + if (status != B_OK) + return status; + return InboundProtocol::MarkMessageAsRead(ref, flag); } diff --git a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPInboundProtocol.h b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPInboundProtocol.h index f907fc3e9e..998a2243c1 100644 --- a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPInboundProtocol.h +++ b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPInboundProtocol.h @@ -101,7 +101,7 @@ public: virtual status_t SyncMessages(); virtual status_t FetchBody(const entry_ref& ref); virtual status_t MarkMessageAsRead(const entry_ref& ref, - bool read = true); + read_flags flag = B_READ); virtual status_t DeleteMessage(const entry_ref& ref); virtual status_t AppendMessage(const entry_ref& ref); diff --git a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPRootInboundProtocol.cpp b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPRootInboundProtocol.cpp index 196bde69b3..9d51f85309 100644 --- a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPRootInboundProtocol.cpp +++ b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPRootInboundProtocol.cpp @@ -98,14 +98,15 @@ IMAPRootInboundProtocol::FetchBody(const entry_ref& ref) status_t -IMAPRootInboundProtocol::MarkMessageAsRead(const entry_ref& ref, bool read) +IMAPRootInboundProtocol::MarkMessageAsRead(const entry_ref& ref, + read_flags flag) { if (InterestingEntry(ref)) - return IMAPInboundProtocol::MarkMessageAsRead(ref, read); + return IMAPInboundProtocol::MarkMessageAsRead(ref, flag); InboundProtocolThread* thread = _FindThreadFor(ref); if (!thread) return B_BAD_VALUE; - thread->MarkMessageAsRead(ref, read); + thread->MarkMessageAsRead(ref, flag); return B_OK; } diff --git a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPRootInboundProtocol.h b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPRootInboundProtocol.h index 1b1acd9ca3..29e77a25d8 100644 --- a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPRootInboundProtocol.h +++ b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPRootInboundProtocol.h @@ -33,7 +33,7 @@ public: status_t SyncMessages(); status_t FetchBody(const entry_ref& ref); status_t MarkMessageAsRead(const entry_ref& ref, - bool read = true); + read_flags flag = B_READ); status_t DeleteMessage(const entry_ref& ref); status_t AppendMessage(const entry_ref& ref); diff --git a/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/IMAPStorage.cpp b/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/IMAPStorage.cpp index 74c88d0f24..2b5f29f750 100644 --- a/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/IMAPStorage.cpp +++ b/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/IMAPStorage.cpp @@ -468,10 +468,6 @@ IMAPStorage::_WriteFlags(int32 flags, BNode& node) if (writen != sizeof(int32)) return writen; - const char* statusString = (flags & kSeen) ? "Read" : "New"; - node.WriteAttr(B_MAIL_ATTR_STATUS, B_STRING_TYPE, 0, statusString, - strlen(statusString)); - return B_OK; } diff --git a/src/add-ons/mail_daemon/inbound_protocols/pop3/pop3.cpp b/src/add-ons/mail_daemon/inbound_protocols/pop3/pop3.cpp index e84c5e933d..3c0aba613f 100644 --- a/src/add-ons/mail_daemon/inbound_protocols/pop3/pop3.cpp +++ b/src/add-ons/mail_daemon/inbound_protocols/pop3/pop3.cpp @@ -184,9 +184,6 @@ POP3Protocol::SyncMessages() entry_ref ref; entry.GetRef(&ref); - // the ref becomes invalid after renaming the file thus we already - // write the status here - MarkMessageAsRead(ref, false); int32 size = MessageSize(toRetrieve); if (fFetchBodyLimit < 0 || size <= fFetchBodyLimit) { diff --git a/src/add-ons/mail_daemon/outbound_protocols/smtp/ConfigView.cpp b/src/add-ons/mail_daemon/outbound_protocols/smtp/ConfigView.cpp index d46048df1f..05766a2a8c 100644 --- a/src/add-ons/mail_daemon/outbound_protocols/smtp/ConfigView.cpp +++ b/src/add-ons/mail_daemon/outbound_protocols/smtp/ConfigView.cpp @@ -71,7 +71,7 @@ SMTPConfigView::SMTPConfigView(MailAddonSettings& settings, SetTo(settings); fFileView = new BMailFileConfigView("Destination:", "destination", - false, kDefaultSentDirectory); + false, default_sent_directory()); fFileView->SetTo(&settings.Settings(), NULL); AddChild(fFileView); float w, h; diff --git a/src/apps/mail/MailWindow.cpp b/src/apps/mail/MailWindow.cpp index 62052bfc17..029c20c28a 100644 --- a/src/apps/mail/MailWindow.cpp +++ b/src/apps/mail/MailWindow.cpp @@ -852,12 +852,12 @@ TMailWindow::SetCurrentMessageRead(bool read) if (read && !mailStatus.ICompare("New")) { node.RemoveAttr(B_MAIL_ATTR_STATUS); WriteAttrString(&node, B_MAIL_ATTR_STATUS, "Read"); - BMailDaemon::MarkAsRead(account, *fRef, true); + BMailDaemon::MarkAsRead(account, *fRef, B_READ); } if (!read && !mailStatus.ICompare("Read")) { node.RemoveAttr(B_MAIL_ATTR_STATUS); WriteAttrString(&node, B_MAIL_ATTR_STATUS, "New"); - BMailDaemon::MarkAsRead(account, *fRef, false); + BMailDaemon::MarkAsRead(account, *fRef, B_UNREAD); } } diff --git a/src/kits/mail/HaikuMailFormatFilter.cpp b/src/kits/mail/HaikuMailFormatFilter.cpp index f1a8ae2f1c..88efba3d45 100644 --- a/src/kits/mail/HaikuMailFormatFilter.cpp +++ b/src/kits/mail/HaikuMailFormatFilter.cpp @@ -54,14 +54,18 @@ HaikuMailFormatFilter::HaikuMailFormatFilter(MailProtocol& protocol, fAccountId(settings->AccountID()) { const BMessage* outboundSettings = &settings->OutboundSettings().Settings(); - fOutboundDirectory = kDefaultSentDirectory; - outboundSettings->FindString("destination", &fOutboundDirectory); + if (outboundSettings->FindString("destination", &fOutboundDirectory) + != B_OK) { + fOutboundDirectory = default_sent_directory(); + } } void HaikuMailFormatFilter::HeaderFetched(const entry_ref& ref, BFile* file) { + write_read_attr(*file, B_UNREAD); + file->Seek(0, SEEK_SET); BMessage attributes; diff --git a/src/kits/mail/MailDaemon.cpp b/src/kits/mail/MailDaemon.cpp index 7ee3de1d40..ff1669b3bb 100644 --- a/src/kits/mail/MailDaemon.cpp +++ b/src/kits/mail/MailDaemon.cpp @@ -71,7 +71,7 @@ BMailDaemon::CountNewMessages(bool wait_for_fetch_completion) status_t -BMailDaemon::MarkAsRead(int32 account, const entry_ref& ref, bool read) +BMailDaemon::MarkAsRead(int32 account, const entry_ref& ref, read_flags flag) { BMessenger daemon("application/x-vnd.Be-POST"); if (!daemon.IsValid()) @@ -80,7 +80,7 @@ BMailDaemon::MarkAsRead(int32 account, const entry_ref& ref, bool read) BMessage message(kMsgMarkMessageAsRead); message.AddInt32("account", account); message.AddRef("ref", &ref); - message.AddBool("read", read); + message.AddInt32("read", flag); return daemon.SendMessage(&message); } diff --git a/src/kits/mail/MailProtocol.cpp b/src/kits/mail/MailProtocol.cpp index 16d79f4d07..ff9e3af147 100644 --- a/src/kits/mail/MailProtocol.cpp +++ b/src/kits/mail/MailProtocol.cpp @@ -25,6 +25,7 @@ #include +#include #include #include #include @@ -403,14 +404,10 @@ InboundProtocol::AppendMessage(const entry_ref& ref) status_t -InboundProtocol::MarkMessageAsRead(const entry_ref& ref, bool read) +InboundProtocol::MarkMessageAsRead(const entry_ref& ref, read_flags flag) { BNode node(&ref); - const char* statusString = (read == true) ? "Read" : "New"; - if (node.WriteAttr(B_MAIL_ATTR_STATUS, B_STRING_TYPE, 0, statusString, - strlen(statusString)) < 0) - return B_ERROR; - return B_OK; + return write_read_attr(node, flag); } @@ -603,7 +600,7 @@ InboundProtocolThread::MessageReceived(BMessage* message) { entry_ref ref; message->FindRef("ref", &ref); - bool read = message->FindBool("read"); + read_flags read = (read_flags)message->FindInt32("read"); fProtocol->MarkMessageAsRead(ref, read); break; } @@ -648,11 +645,11 @@ InboundProtocolThread::FetchBody(const entry_ref& ref, BMessage* launch) void -InboundProtocolThread::MarkMessageAsRead(const entry_ref& ref, bool read) +InboundProtocolThread::MarkMessageAsRead(const entry_ref& ref, read_flags flag) { BMessage message(kMsgMarkMessageAsRead); message.AddRef("ref", &ref); - message.AddBool("read", read); + message.AddInt32("read", flag); PostMessage(&message); } diff --git a/src/kits/mail/MailSettings.cpp b/src/kits/mail/MailSettings.cpp index 8f36495255..226f7f4f57 100644 --- a/src/kits/mail/MailSettings.cpp +++ b/src/kits/mail/MailSettings.cpp @@ -31,6 +31,17 @@ namespace MailInternal { } +BString +default_sent_directory() +{ + BPath path; + if (find_directory(B_USER_DIRECTORY, &path) != B_OK) + path.SetTo("/boot/home"); + path.Append("mail/sent"); + return path.Path(); +} + + // #pragma mark - BMailSettings diff --git a/src/kits/mail/mail_util.cpp b/src/kits/mail/mail_util.cpp index 5be1dcb807..7f452f4ec3 100644 --- a/src/kits/mail/mail_util.cpp +++ b/src/kits/mail/mail_util.cpp @@ -86,6 +86,25 @@ extern const CharsetConversionEntry mail_charsets [] = }; +status_t +write_read_attr(BNode& node, read_flags flag) +{ + if (node.WriteAttr(B_MAIL_ATTR_READ, B_INT32_TYPE, 0, &flag, sizeof(int32)) + < 0) + return B_ERROR; + + if (flag == B_SEEN) + return B_OK; + + const char* statusString = (flag == B_READ) ? "Read" : "New"; + if (node.WriteAttr(B_MAIL_ATTR_STATUS, B_STRING_TYPE, 0, statusString, + strlen(statusString)) < 0) + return B_ERROR; + + return B_OK; +} + + // The next couple of functions are our wrapper around convert_to_utf8 and // convert_from_utf8 so that they can also convert from UTF-8 to UTF-8 by // specifying the B_MAIL_UTF8_CONVERSION constant as the conversion operation. It diff --git a/src/servers/mail/MailDaemon.cpp b/src/servers/mail/MailDaemon.cpp index aa1277adb3..443fbf767f 100644 --- a/src/servers/mail/MailDaemon.cpp +++ b/src/servers/mail/MailDaemon.cpp @@ -58,6 +58,7 @@ makeIndices() fs_create_index(device, B_MAIL_ATTR_WHEN, B_INT32_TYPE, 0); fs_create_index(device, B_MAIL_ATTR_FLAGS, B_INT32_TYPE, 0); fs_create_index(device, B_MAIL_ATTR_ACCOUNT, B_INT32_TYPE, 0); + fs_create_index(device, B_MAIL_ATTR_READ, B_INT32_TYPE, 0); } } @@ -432,7 +433,7 @@ MailDaemonApp::MessageReceived(BMessage* msg) entry_ref ref; if (msg->FindRef("ref", &ref) != B_OK) break; - bool read = msg->FindBool("read"); + read_flags read = (read_flags)msg->FindInt32("read"); AccountMap::iterator it = fAccounts.find(account); if (it == fAccounts.end()) break; @@ -670,6 +671,8 @@ MailDaemonApp::MakeMimeTypes(bool remakeMIMETypes) addAttribute(info, B_MAIL_ATTR_THREAD, "Thread"); addAttribute(info, B_MAIL_ATTR_ACCOUNT, "Account", B_STRING_TYPE, true, false, 100); + addAttribute(info, B_MAIL_ATTR_READ, "Read", B_INT32_TYPE, + true, false, 70); mime.SetAttrInfo(&info); if (i == 0) {