diff --git a/po/POTFILES.in b/po/POTFILES.in index 6279475f..521a3d52 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -277,6 +277,7 @@ src/engine/memory/memory-byte-buffer.vala src/engine/memory/memory-empty-buffer.vala src/engine/memory/memory-file-buffer.vala src/engine/memory/memory-growable-buffer.vala +src/engine/memory/memory-offset-buffer.vala src/engine/memory/memory-string-buffer.vala src/engine/memory/memory-unowned-byte-array-buffer.vala src/engine/memory/memory-unowned-bytes-buffer.vala diff --git a/sql/version-017.sql b/sql/version-017.sql new file mode 100644 index 00000000..f1cb4d33 --- /dev/null +++ b/sql/version-017.sql @@ -0,0 +1,7 @@ +-- +-- We're now keeping sent mail around after sending, so we can also push it up +-- to the Sent Mail folder. This column lets us keep track of the state of +-- messages in the outbox. +-- + +ALTER TABLE SmtpOutboxTable ADD COLUMN sent INTEGER DEFAULT 0; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4c3a45a1..4a04d926 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -218,6 +218,7 @@ engine/memory/memory-byte-buffer.vala engine/memory/memory-empty-buffer.vala engine/memory/memory-file-buffer.vala engine/memory/memory-growable-buffer.vala +engine/memory/memory-offset-buffer.vala engine/memory/memory-string-buffer.vala engine/memory/memory-unowned-byte-array-buffer.vala engine/memory/memory-unowned-bytes-buffer.vala diff --git a/src/client/accounts/add-edit-page.vala b/src/client/accounts/add-edit-page.vala index d8f5830c..edcb7b5b 100644 --- a/src/client/accounts/add-edit-page.vala +++ b/src/client/accounts/add-edit-page.vala @@ -50,6 +50,11 @@ public class AddEditPage : Gtk.Box { set { check_remember_password.active = value; } } + public bool save_sent_mail { + get { return check_save_sent_mail.active; } + set { check_save_sent_mail.active = value; } + } + public string smtp_username { get { return entry_smtp_username.text; } set { entry_smtp_username.text = value; } @@ -139,6 +144,7 @@ public class AddEditPage : Gtk.Box { private Gtk.Entry entry_nickname; private Gtk.ComboBoxText combo_service; private Gtk.CheckButton check_remember_password; + private Gtk.CheckButton check_save_sent_mail; private Gtk.Alignment other_info; @@ -198,6 +204,7 @@ public class AddEditPage : Gtk.Box { label_password = (Gtk.Label) builder.get_object("label: password"); entry_password = (Gtk.Entry) builder.get_object("entry: password"); check_remember_password = (Gtk.CheckButton) builder.get_object("check: remember_password"); + check_save_sent_mail = (Gtk.CheckButton) builder.get_object("check: save_sent_mail"); label_error = (Gtk.Label) builder.get_object("label: error"); @@ -242,6 +249,7 @@ public class AddEditPage : Gtk.Box { entry_real_name.changed.connect(on_changed); entry_nickname.changed.connect(on_changed); check_remember_password.toggled.connect(on_changed); + check_save_sent_mail.toggled.connect(on_changed); combo_service.changed.connect(on_changed); entry_imap_host.changed.connect(on_changed); entry_imap_port.changed.connect(on_changed); @@ -280,6 +288,8 @@ public class AddEditPage : Gtk.Box { info.smtp_credentials != null ? info.smtp_credentials.user : null, info.smtp_credentials != null ? info.smtp_credentials.pass : null, info.service_provider, + info.save_sent_mail, + info.allow_save_sent_mail(), info.default_imap_server_host, info.default_imap_server_port, info.default_imap_server_ssl, @@ -304,6 +314,8 @@ public class AddEditPage : Gtk.Box { string? initial_smtp_username = null, string? initial_smtp_password = null, int initial_service_provider = Geary.ServiceProvider.GMAIL, + bool initial_save_sent_mail = true, + bool allow_save_sent_mail = true, string? initial_default_imap_host = null, uint16 initial_default_imap_port = Geary.Imap.ClientConnection.DEFAULT_PORT_SSL, bool initial_default_imap_ssl = true, @@ -322,6 +334,8 @@ public class AddEditPage : Gtk.Box { email_address = initial_email ?? ""; password = initial_imap_password != null ? initial_imap_password : ""; remember_password = initial_remember_password; + save_sent_mail = initial_save_sent_mail; + check_save_sent_mail.sensitive = allow_save_sent_mail; set_service_provider((Geary.ServiceProvider) initial_service_provider); combo_imap_encryption.active = Encryption.NONE; // Must be default; set to real value below. combo_smtp_encryption.active = Encryption.NONE; @@ -538,6 +552,7 @@ public class AddEditPage : Gtk.Box { account_information.imap_remember_password = remember_password; account_information.smtp_remember_password = remember_password; account_information.service_provider = get_service_provider(); + account_information.save_sent_mail = save_sent_mail; account_information.default_imap_server_host = imap_host; account_information.default_imap_server_port = imap_port; account_information.default_imap_server_ssl = imap_ssl; @@ -573,6 +588,7 @@ public class AddEditPage : Gtk.Box { welcome_box.visible = mode == PageMode.WELCOME; entry_nickname.visible = label_nickname.visible = mode != PageMode.WELCOME; storage_container.visible = mode == PageMode.EDIT; + check_save_sent_mail.visible = mode != PageMode.WELCOME; if (get_service_provider() == Geary.ServiceProvider.OTHER) { // Display all options for custom providers. diff --git a/src/client/application/geary-controller.vala b/src/client/application/geary-controller.vala index 6218f56a..6b61deab 100644 --- a/src/client/application/geary-controller.vala +++ b/src/client/application/geary-controller.vala @@ -653,7 +653,11 @@ public class GearyController : Geary.BaseObject { break; case Geary.Account.Problem.EMAIL_DELIVERY_FAILURE: - handle_send_failure(); + handle_outbox_failure(StatusBar.Message.OUTBOX_SEND_FAILURE); + break; + + case Geary.Account.Problem.SAVE_SENT_MAIL_FAILED: + handle_outbox_failure(StatusBar.Message.OUTBOX_SAVE_SENT_MAIL_FAILED); break; default: @@ -661,7 +665,7 @@ public class GearyController : Geary.BaseObject { } } - private void handle_send_failure() { + private void handle_outbox_failure(StatusBar.Message message) { bool activate_message = false; try { // Due to a timing hole where it's possible to delete a message @@ -685,16 +689,29 @@ public class GearyController : Geary.BaseObject { } if (activate_message) { - if (!main_window.status_bar.is_message_active(StatusBar.Message.OUTBOX_SEND_FAILURE)) - main_window.status_bar.activate_message(StatusBar.Message.OUTBOX_SEND_FAILURE); - libnotify.set_error_notification(_("Error sending email"), - _("Geary encountered an error sending an email. If the problem persists, please manually delete the email from your Outbox folder.")); + if (!main_window.status_bar.is_message_active(message)) + main_window.status_bar.activate_message(message); + switch (message) { + case StatusBar.Message.OUTBOX_SEND_FAILURE: + libnotify.set_error_notification(_("Error sending email"), + _("Geary encountered an error sending an email. If the problem persists, please manually delete the email from your Outbox folder.")); + break; + + case StatusBar.Message.OUTBOX_SAVE_SENT_MAIL_FAILED: + libnotify.set_error_notification(_("Error saving sent mail"), + _("Geary encountered an error saving a sent message to Sent Mail. The message will stay in your Outbox folder until you delete it.")); + break; + + default: + assert_not_reached(); + } } } private void on_account_email_removed(Geary.Folder folder, Gee.Collection ids) { if (folder.special_folder_type == Geary.SpecialFolderType.OUTBOX) { main_window.status_bar.deactivate_message(StatusBar.Message.OUTBOX_SEND_FAILURE); + main_window.status_bar.deactivate_message(StatusBar.Message.OUTBOX_SAVE_SENT_MAIL_FAILED); libnotify.clear_error_notification(); } } diff --git a/src/client/components/status-bar.vala b/src/client/components/status-bar.vala index 95c877b1..6a7bf582 100644 --- a/src/client/components/status-bar.vala +++ b/src/client/components/status-bar.vala @@ -16,7 +16,8 @@ public class StatusBar : Gtk.Statusbar { public enum Message { OUTBOX_SENDING, - OUTBOX_SEND_FAILURE; + OUTBOX_SEND_FAILURE, + OUTBOX_SAVE_SENT_MAIL_FAILED; internal string get_text() { switch (this) { @@ -26,6 +27,10 @@ public class StatusBar : Gtk.Statusbar { case Message.OUTBOX_SEND_FAILURE: /// Displayed in the space-limited status bar when a message fails to be sent due to error. return _("Error sending email"); + case Message.OUTBOX_SAVE_SENT_MAIL_FAILED: + // Displayed in the space-limited status bar when a message fails to be uploaded + // to Sent Mail after being sent. + return _("Error saving sent mail"); default: assert_not_reached(); } @@ -37,6 +42,8 @@ public class StatusBar : Gtk.Statusbar { return Context.OUTBOX; case Message.OUTBOX_SEND_FAILURE: return Context.OUTBOX; + case Message.OUTBOX_SAVE_SENT_MAIL_FAILED: + return Context.OUTBOX; default: assert_not_reached(); } diff --git a/src/client/composer/composer-window.vala b/src/client/composer/composer-window.vala index f1532a67..0f8f5b0b 100644 --- a/src/client/composer/composer-window.vala +++ b/src/client/composer/composer-window.vala @@ -850,7 +850,7 @@ public class ComposerWindow : Gtk.Window { // only save HTML drafts to avoid resetting the DOM (which happens when converting the // HTML to flowed text) draft_id = yield drafts_folder.create_email_async(new Geary.RFC822.Message.from_composed_email( - get_composed_email(null, true)), flags, null, draft_id, cancellable); + get_composed_email(null, true), null), flags, null, draft_id, cancellable); draft_save_label.label = DRAFT_SAVED_TEXT; } catch (Error e) { diff --git a/src/client/conversation-viewer/conversation-viewer.vala b/src/client/conversation-viewer/conversation-viewer.vala index c1ea5f93..94375a92 100644 --- a/src/client/conversation-viewer/conversation-viewer.vala +++ b/src/client/conversation-viewer/conversation-viewer.vala @@ -593,6 +593,7 @@ public class ConversationViewer : Gtk.Box { //
//
//