[geary/wip/713247-tls] Fixed for SMTP/Outbox



commit 551b98be86b97c4f3e331e1da5d6749f00544a64
Author: Jim Nelson <jim yorba org>
Date:   Wed Aug 27 16:01:22 2014 -0700

    Fixed for SMTP/Outbox

 src/client/application/geary-controller.vala       |    2 +-
 src/client/dialogs/certificate-warning-dialog.vala |    7 ++-
 src/engine/api/geary-endpoint.vala                 |   21 +++++++++
 src/engine/api/geary-service.vala                  |   22 ++++++++++
 src/engine/imap-db/outbox/smtp-outbox-folder.vala  |   45 ++++++++++++++-----
 src/engine/smtp/smtp-client-connection.vala        |   11 ++++-
 6 files changed, 91 insertions(+), 17 deletions(-)
---
diff --git a/src/client/application/geary-controller.vala b/src/client/application/geary-controller.vala
index cb19076..43af7b6 100644
--- a/src/client/application/geary-controller.vala
+++ b/src/client/application/geary-controller.vala
@@ -520,7 +520,7 @@ public class GearyController : Geary.BaseObject {
                 return;
             
             CertificateWarningDialog dialog = new CertificateWarningDialog(main_window, endpoint,
-                warnings);
+                service, warnings);
             switch (dialog.run()) {
                 case CertificateWarningDialog.Result.TRUST:
                     endpoint.trust_untrusted_host = Geary.Trillian.TRUE;
diff --git a/src/client/dialogs/certificate-warning-dialog.vala 
b/src/client/dialogs/certificate-warning-dialog.vala
index 816402c..b95fc6a 100644
--- a/src/client/dialogs/certificate-warning-dialog.vala
+++ b/src/client/dialogs/certificate-warning-dialog.vala
@@ -17,7 +17,8 @@ public class CertificateWarningDialog {
     private Gtk.Label top_label;
     private Gtk.Label warnings_label;
     
-    public CertificateWarningDialog(Gtk.Window? parent, Geary.Endpoint endpoint, TlsCertificateFlags 
warnings) {
+    public CertificateWarningDialog(Gtk.Window? parent, Geary.Endpoint endpoint, Geary.Service service,
+        TlsCertificateFlags warnings) {
         Gtk.Builder builder = GearyApplication.instance.create_builder("certificate_warning_dialog.glade");
         
         dialog = (Gtk.Dialog) builder.get_object("CertificateWarningDialog");
@@ -27,8 +28,8 @@ public class CertificateWarningDialog {
         dialog.transient_for = parent;
         dialog.modal = true;
         
-        top_label.label = _("The identity of the mail server at %s:%u could not be verified:").printf(
-            endpoint.remote_address.hostname, endpoint.remote_address.port);
+        top_label.label = _("The identity of the %s mail server at %s:%u could not be verified:").printf(
+            service.user_label(), endpoint.remote_address.hostname, endpoint.remote_address.port);
         
         warnings_label.label = generate_warning_list(warnings);
         warnings_label.use_markup = true;
diff --git a/src/engine/api/geary-endpoint.vala b/src/engine/api/geary-endpoint.vala
index bbbd0a1..1386c4a 100644
--- a/src/engine/api/geary-endpoint.vala
+++ b/src/engine/api/geary-endpoint.vala
@@ -66,6 +66,27 @@ public class Geary.Endpoint : BaseObject {
      */
     public Trillian trust_untrusted_host { get; set; default = Trillian.UNKNOWN; }
     
+    /**
+     * Returns true if (a) no TLS warnings have been detected or (b) user has explicitly acceded
+     * to ignoring them and continuing the connection.
+     *
+     * This returns true if no connection has been attempted or connected and STARTTLS has not
+     * been issued.  It's only when a connection is attempted can the certificate be examined
+     * and this can accurately return false.  This behavior allows for a single code path to
+     * first attempt a connection and thereafter only attempt connections when TLS issues have
+     * been resolved by the user.
+     *
+     * @see tls_validation_warnings
+     * @see trust_untrusted_host
+     */
+    public bool is_trusted_or_unconnected {
+        get {
+            return (tls_validation_warnings != 0)
+                ? trust_untrusted_host.is_certain()
+                : trust_untrusted_host.is_possible();
+        }
+    }
+    
     public bool is_ssl { get {
         return flags.is_all_set(Flags.SSL);
     } }
diff --git a/src/engine/api/geary-service.vala b/src/engine/api/geary-service.vala
index 679e9d1..7745293 100644
--- a/src/engine/api/geary-service.vala
+++ b/src/engine/api/geary-service.vala
@@ -4,11 +4,33 @@
  * (version 2.1 or later).  See the COPYING file in this distribution.
  */
 
+/**
+ * The type of mail service provided by a particular destination.
+ */
 public enum Geary.Service {
     IMAP,
     SMTP;
+    
+    /**
+     * Returns a user-visible label for the { link Service}.
+     */
+    public string user_label() {
+        switch (this) {
+            case IMAP:
+                return _("IMAP");
+            
+            case SMTP:
+                return _("SMTP");
+            
+            default:
+                assert_not_reached();
+        }
+    }
 }
 
+/**
+ * A bitfield of { link Service}s.
+ */
 [Flags]
 public enum Geary.ServiceFlag {
     IMAP,
diff --git a/src/engine/imap-db/outbox/smtp-outbox-folder.vala 
b/src/engine/imap-db/outbox/smtp-outbox-folder.vala
index f994786..c190e15 100644
--- a/src/engine/imap-db/outbox/smtp-outbox-folder.vala
+++ b/src/engine/imap-db/outbox/smtp-outbox-folder.vala
@@ -215,16 +215,26 @@ private class Geary.SmtpOutboxFolder : Geary.AbstractLocalFolder, Geary.FolderSu
             }
             
             // Send the message, but only remove from database once sent
+            bool should_nap = false;
+            bool mail_sent = false;
             try {
-                debug("Outbox postman: Sending \"%s\" (ID:%s)...", message_subject(message),
-                    row.outbox_id.to_string());
-                yield send_email_async(message, null);
+                // only try if (a) no TLS issues or (b) user has acknowledged them and says to
+                // continue
+                if (_account.information.get_smtp_endpoint().is_trusted_or_unconnected) {
+                    debug("Outbox postman: Sending \"%s\" (ID:%s)...", message_subject(message),
+                        row.outbox_id.to_string());
+                    yield send_email_async(message, null);
+                    mail_sent = true;
+                } else {
+                    // user was warned via Geary.Engine signal, need to wait for that to be cleared
+                    // befor sending
+                    outbox_queue.send(row);
+                    should_nap = true;
+                }
             } catch (Error send_err) {
                 debug("Outbox postman send error, retrying: %s", send_err.message);
                 
-                outbox_queue.send(row);
-                
-                bool should_nap = true;
+                should_nap = true;
                 
                 if (send_err is SmtpError.AUTHENTICATION_FAILED) {
                     bool report = true;
@@ -243,16 +253,27 @@ private class Geary.SmtpOutboxFolder : Geary.AbstractLocalFolder, Geary.FolderSu
                     
                     if (report)
                         report_problem(Geary.Account.Problem.SEND_EMAIL_LOGIN_FAILED, send_err);
+                } else if (send_err is TlsError) {
+                    // up to application to be aware of problem via Geary.Engine, but do nap and
+                    // try later
+                    debug("TLS connection warnings connecting to %s, user must confirm connection to 
continue",
+                        _account.information.get_smtp_endpoint().to_string());
                 } else {
                     report_problem(Geary.Account.Problem.EMAIL_DELIVERY_FAILURE, send_err);
                 }
+            }
+            
+            if (should_nap) {
+                debug("Outbox napping for %u seconds...", send_retry_seconds);
                 
-                if (should_nap) {
-                    // Take a brief nap before continuing to allow connection problems to resolve.
-                    yield Geary.Scheduler.sleep_async(send_retry_seconds);
-                    send_retry_seconds *= 2;
-                    send_retry_seconds = Geary.Numeric.uint_ceiling(send_retry_seconds, 
MAX_SEND_RETRY_INTERVAL_SEC);
-                }
+                // Take a brief nap before continuing to allow connection problems to resolve.
+                yield Geary.Scheduler.sleep_async(send_retry_seconds);
+                send_retry_seconds = Geary.Numeric.uint_ceiling(send_retry_seconds * 2, 
MAX_SEND_RETRY_INTERVAL_SEC);
+            }
+            
+            if (!mail_sent) {
+                // don't drop row until it's sent
+                outbox_queue.send(row);
                 
                 continue;
             }
diff --git a/src/engine/smtp/smtp-client-connection.vala b/src/engine/smtp/smtp-client-connection.vala
index f629a64..1010eed 100644
--- a/src/engine/smtp/smtp-client-connection.vala
+++ b/src/engine/smtp/smtp-client-connection.vala
@@ -48,9 +48,18 @@ public class Geary.Smtp.ClientConnection {
         if (cx == null)
             return false;
         
-        yield cx.close_async(Priority.DEFAULT, cancellable);
+        Error? disconnect_error = null;
+        try {
+            yield cx.close_async(Priority.DEFAULT, cancellable);
+        } catch (Error err) {
+            disconnect_error = err;
+        }
+        
         cx = null;
         
+        if (disconnect_error != null)
+            throw disconnect_error;
+        
         return true;
     }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]