← Back to team overview

deja-dup-team team mailing list archive

[Merge] lp:~aladin/deja-dup/imap-support into lp:deja-dup

 

Lars J. has proposed merging lp:~aladin/deja-dup/imap-support into lp:deja-dup.

Requested reviews:
  Déjà Dup Maintainers (deja-dup-team)
Related bugs:
  #529167 Support IMAP backups
  https://bugs.launchpad.net/bugs/529167

For more details, see:
https://code.launchpad.net/~aladin/deja-dup/imap-support/+merge/46248

This branch implements imap support.

- Pay attention to Duplicity Bug #385495
- po/deja-dup.pot is removed from my branch. Why? I run make update-pot
- The list of known IMAP service providers is hard-coded in common/IMAP_Configuration_Helper.vala. In the future it is better to maintain the list in a extra file.

-- 
https://code.launchpad.net/~aladin/deja-dup/imap-support/+merge/46248
Your team Déjà Dup Maintainers is requested to review the proposed merge of lp:~aladin/deja-dup/imap-support into lp:deja-dup.
=== modified file '.bzrignore'
--- .bzrignore	2010-12-29 18:29:25 +0000
+++ .bzrignore	2011-01-14 10:52:53 +0000
@@ -1,5 +1,7 @@
 common/BackendFile.c
 common/BackendRackspace.c
+common/BackendIMAP.c
+common/IMAP_Configuration_Helper.c
 common/BackendS3.c
 common/BackendU1.c
 common/Backend.c
@@ -45,6 +47,7 @@
 widgets/ConfigLocationFTP.c
 widgets/ConfigLocationFile.c
 widgets/ConfigLocationRackspace.c
+widgets/ConfigLocationIMAP.c
 widgets/ConfigLocationS3.c
 widgets/ConfigLocationSMB.c
 widgets/ConfigLocationSSH.c

=== modified file 'AUTHORS'
--- AUTHORS	2010-12-23 01:23:54 +0000
+++ AUTHORS	2011-01-14 10:52:53 +0000
@@ -8,6 +8,7 @@
            2009–2010 Andrew Fister <temposs@xxxxxxxxx>
            2010 Michael Vogt <michael.vogt@xxxxxxxxxx>
            2010 Urban Skudnik <urban.skudnik@xxxxxxxxx>
+           2011 Lars Jegenhorst <dev.lars@xxxxxxxxxxxxx>
 License: GPL-3+
 
 Files: po/*.po

=== modified file 'common/Backend.vala'
--- common/Backend.vala	2010-12-26 19:13:56 +0000
+++ common/Backend.vala	2011-01-14 10:52:53 +0000
@@ -59,6 +59,7 @@
         backend != "s3" &&
         backend != "rackspace" &&
         backend != "u1" &&
+        backend != "imap" &&
         backend != "file")
       backend = "auto"; // default to auto if string is not known
 
@@ -80,6 +81,8 @@
       return new BackendS3();
     else if (backend_name == "u1")
       return new BackendU1();
+    else if (backend_name == "imap")
+      return new BackendIMAP();
     else if (backend_name == "rackspace")
       return new BackendRackspace();
     else if (backend_name == "file")

=== added file 'common/BackendIMAP.vala'
--- common/BackendIMAP.vala	1970-01-01 00:00:00 +0000
+++ common/BackendIMAP.vala	2011-01-14 10:52:53 +0000
@@ -0,0 +1,171 @@
+/* -*- Mode: Vala; indent-tabs-mode: nil; tab-width: 2 -*- */
+/*
+    This file is part of Déjà Dup.
+    © 2008–2010 Michael Terry <mike@xxxxxxxxxxx>
+    © 2011 Lars Jegenhorst <dev.lars@xxxxxxxxxxxxx>
+
+    Déjà Dup is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    Déjà Dup is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with Déjà Dup.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+using GLib, GLib.Environment;
+
+namespace DejaDup {
+
+public const string IMAP_ROOT = "IMAP";
+public const string IMAP_EMAIL_ADDRESS = "email-address";   // this is also used as the username of the imap account
+public const string IMAP_SERVER = "server-address";
+public const string IMAP_ATTACHMENT_SIZE = "attachment-size";  // size of the email attachment
+public const string IMAP_USE_IMAPS = "use-imaps";
+public const string IMAP_MAILBOX = "mailbox";
+public const string IMAP_FROM_ADDRESS_PREFIX = "from-address-prefix"; // on restore (or list) command the from_address_prefix will distinguish between different backups.
+
+public class BackendIMAP : Backend
+{
+
+  private Settings settings = get_settings(IMAP_ROOT); 
+  private string settings_id;
+  private string id;
+  private string secret_key;
+
+  public override Backend clone() {
+    return new BackendIMAP();
+  }
+  
+  public override void add_argv(Operation.Mode mode, ref List<string> argv) {
+    argv.append("--volsize=%d".printf(settings.get_int(IMAP_ATTACHMENT_SIZE)));
+    var mailbox = settings.get_string(IMAP_MAILBOX);
+    if (mailbox != null && mailbox != "" && mailbox != "INBOX")
+      argv.append("--imap-mailbox=%s".printf(mailbox));
+  }
+  
+  public override bool is_native() {
+    return false;
+  }
+  
+  public override bool is_ready(out string when) {
+    when = _("Backup will begin when a network connection becomes available.");
+    return Network.get().connected;
+  }
+
+  private string? get_protocol() {
+    string protocol = settings.get_boolean(IMAP_USE_IMAPS) ? "imaps" : "imap";
+    return protocol;
+  }
+
+  /**
+   * duplicity syntax:
+   * imap[s]://username[:password]@host.com[/from_address_prefix]
+   */
+  public override string? get_location() throws Error {
+    string location = "%s://%s@%s".printf(get_protocol(), settings.get_string(IMAP_EMAIL_ADDRESS), settings.get_string(IMAP_SERVER));
+    var from_address_prefix = settings.get_string(IMAP_FROM_ADDRESS_PREFIX);
+    if (from_address_prefix != null && from_address_prefix != "")
+      location += "/%s".printf(from_address_prefix);
+    return location;
+  }
+    
+  /**
+   * Syntax: email-address[/mailbox]
+   */
+  public override string? get_location_pretty() throws Error {
+    var location = settings.get_string(IMAP_EMAIL_ADDRESS);
+    var mailbox = settings.get_string(IMAP_MAILBOX);
+    if (mailbox != null && mailbox != "" && mailbox != "INBOX")
+      location += "/" + mailbox;
+    return location;
+  }
+  
+  public override async void get_envp() throws Error {
+    settings_id = settings.get_string(IMAP_EMAIL_ADDRESS);
+    id = settings_id == null ? "" : settings_id;
+   
+    if (id != "" && secret_key != null) {
+      // We've already been run before and got the key
+      got_secret_key();
+      return;
+    }
+    
+    if (id != "") {
+      // First, try user's keyring
+      secret_key = null;
+      GnomeKeyring.find_network_password(id, null, settings.get_string(IMAP_SERVER), null, get_protocol(),
+                                         null, 0, found_password);
+    }
+    else
+      ask_password();
+  }
+  
+  void found_password(GnomeKeyring.Result result,
+                      GLib.List<GnomeKeyring.NetworkPasswordData>? list)
+  {
+    if (result == GnomeKeyring.Result.OK && list != null) {
+      secret_key = list.data.password;
+      got_secret_key();
+    }
+    else {
+      ask_password();
+    }
+  }
+  
+  void save_password_callback(GnomeKeyring.Result result, uint32 val)
+  {
+  }
+  
+  void got_password_reply(MountOperation mount_op, MountOperationResult result)
+  {
+    if (result != MountOperationResult.HANDLED) {
+      envp_ready(false, new List<string>(), _("Permission denied"));
+      return;
+    }
+
+    id = mount_op.username;
+    secret_key = mount_op.password;
+
+    // Save it
+    var remember = mount_op.password_save;
+    if (remember != PasswordSave.NEVER) {
+      string where = (remember == PasswordSave.FOR_SESSION) ?
+                     "session" : GnomeKeyring.DEFAULT;
+      GnomeKeyring.set_network_password(where, id, null, settings.get_string(IMAP_SERVER), null,
+                                        get_protocol(), null, 0, secret_key,
+                                        save_password_callback);
+    }
+    
+    got_secret_key();
+  }
+
+  void ask_password() {
+    mount_op.set("label_help", _("Email account: %s").printf(id));
+    mount_op.set("label_password", _("Email account password:"));
+    mount_op.set("label_show_password", _("_Show password"));
+    mount_op.set("label_remember_password", _("_Remember password"));
+    mount_op.reply.connect(got_password_reply);
+    mount_op.ask_password(_("Enter your email account password"), id, "",
+                          AskPasswordFlags.NEED_PASSWORD |
+                          AskPasswordFlags.NEED_USERNAME |
+                          AskPasswordFlags.SAVING_SUPPORTED);
+  }
+  
+  void got_secret_key() {
+    if (id != settings_id)
+      settings.set_string(IMAP_EMAIL_ADDRESS, id);
+    
+    List<string> envp = new List<string>();
+    envp.append("IMAP_PASSWORD=%s".printf(secret_key));
+    envp_ready(true, envp);
+  }
+}
+
+} // end namespace
+

=== added file 'common/IMAP_Configuration_Helper.vala'
--- common/IMAP_Configuration_Helper.vala	1970-01-01 00:00:00 +0000
+++ common/IMAP_Configuration_Helper.vala	2011-01-14 10:52:53 +0000
@@ -0,0 +1,101 @@
+/* -*- Mode: Vala; indent-tabs-mode: nil; tab-width: 2 -*- */
+/*
+    This file is part of Déjà Dup.
+    © 2011 Lars Jegenhorst <dev.lars@xxxxxxxxxxxxx>
+
+    Déjà Dup is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    Déjà Dup is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with Déjà Dup.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+
+*/
+using GLib;
+
+namespace DejaDup {
+
+public class IMAP_Provider {
+
+  public string imap_server_address { get; private set; }   // may contain port number
+  public bool use_imaps { get; private set; }               // use imaps or imap
+  public uint maximum_attachment_size { get; private set; } // The maximum email-attachment size the IMAP provider does accept; specified in MB
+
+  public IMAP_Provider (string _imap_server_address, bool _use_imaps, uint _maximum_attachment_size) {
+    imap_server_address = _imap_server_address;
+    use_imaps = _use_imaps;
+    maximum_attachment_size = _maximum_attachment_size;
+  }
+}
+
+/*
+* For a given email-address help the user to config his imap settings.
+*/
+public class IMAP_Configuration_Helper {
+
+  private static IMAP_Configuration_Helper singleton;
+  private HashTable<string, IMAP_Provider> known_providers = new HashTable<string, IMAP_Provider>(str_hash, str_equal);
+  private Regex domain_matching;
+
+  public static IMAP_Configuration_Helper getInstance() throws RegexError {
+    lock (singleton) {
+      if (singleton == null)
+        singleton = new IMAP_Configuration_Helper();
+    }
+    return singleton;
+  }
+
+  private IMAP_Configuration_Helper() throws  RegexError {
+    init_known_imap_providers();
+    domain_matching = new Regex ("""^[A-Z0-9._%+-]+@([A-Z0-9.-]+\.[A-Z]{2,4})$""", RegexCompileFlags.CASELESS);
+  }
+
+  private void register_imap_provider(string[] domains, IMAP_Provider provider) {
+    for (int i=0; i < domains.length; i++)
+      known_providers.insert(domains[i], provider);
+  }
+
+  private void init_known_imap_providers() {
+    register_imap_provider ({"googlemail.com"}, new IMAP_Provider("imap.googlemail.com", true, 20));
+    register_imap_provider ({"gmail.com"}, new IMAP_Provider("imap.gmail.com", true, 20));
+  }
+
+  public bool is_known_configuration(string email_address, string imap_server_address, bool use_imaps, int attachment_size) {
+    MatchInfo match;
+    IMAP_Provider kp = null;
+    if (domain_matching.match(email_address.down(),0, out match)) {
+      string domain = match.fetch(1);
+      if (domain!=null && domain.length > 0) 
+        kp = (IMAP_Provider)known_providers.lookup(domain);
+      return (kp != null && kp.imap_server_address == imap_server_address.down()
+              && kp.use_imaps == use_imaps && kp.maximum_attachment_size >= attachment_size);
+    }
+    return false;
+  }
+  
+  /**
+  * @param email_address
+  * @return returns NULL if email_address is not found
+  */
+  public IMAP_Provider get_imap_provider_details(string email_address) throws RegexError {
+    MatchInfo match;
+    if (domain_matching.match(email_address.down(),0, out match)) {
+      string domain = match.fetch(1);
+      if (domain!=null && domain.length > 0) 
+        return (IMAP_Provider)known_providers.lookup(domain);
+    }
+    return (IMAP_Provider)null;
+  }
+
+}
+
+} // Namespace

=== modified file 'common/Makefile.am'
--- common/Makefile.am	2010-12-26 19:13:56 +0000
+++ common/Makefile.am	2011-01-14 10:52:53 +0000
@@ -31,6 +31,8 @@
 	BackendRackspace.vala \
 	BackendS3.vala \
 	BackendU1.vala \
+	BackendIMAP.vala \
+  IMAP_Configuration_Helper.vala \
 	CommonUtils.vala \
 	Duplicity.vala \
 	DuplicityInfo.vala \

=== modified file 'data/org.gnome.DejaDup.gschema.xml.in'
--- data/org.gnome.DejaDup.gschema.xml.in	2011-01-10 02:29:04 +0000
+++ data/org.gnome.DejaDup.gschema.xml.in	2011-01-14 10:52:53 +0000
@@ -49,6 +49,7 @@
         <choice value='s3'/>
         <choice value='ssh'/>
         <choice value='u1'/>
+        <choice value='imap'/>
       </choices>
       <default>'auto'</default>
       <_summary>Type of location to store backup</_summary>
@@ -57,6 +58,7 @@
     <child name="rackspace" schema="org.gnome.DejaDup.Rackspace"/>
     <child name="s3" schema="org.gnome.DejaDup.S3"/>
     <child name="u1" schema="org.gnome.DejaDup.U1"/>
+    <child name="imap" schema="org.gnome.DejaDup.IMAP"/>
     <child name="file" schema="org.gnome.DejaDup.File"/>
   </schema>
   <schema id="org.gnome.DejaDup.S3" path="/org/gnome/deja-dup/s3/">
@@ -95,6 +97,39 @@
       <_description>The folder name to store files in.  If '$HOSTNAME', it will default to a folder based on the name of the computer.</_description>
     </key>
   </schema>
+  <schema path="/org/gnome/deja-dup/imap/" id="org.gnome.DejaDup.IMAP">
+    <key name="email-address" type="s">
+      <default>''</default>
+      <_summary>Your email-address</_summary>
+      <_description>The email-address corresponding to the IMAP account you want to use as storage provider.</_description>
+    </key>
+    <key name="server-address" type="s">
+      <default>''</default>
+      <_summary>The address of your imap-server</_summary>
+      <_description>The address of your imap-server. May contain the port-number separated by a colon.</_description>
+    </key>
+    <key name="use-imaps" type="b">
+      <default>true</default>
+      <_summary>Use IMAPS (SSL) or IMAP</_summary>
+      <_description>Connect to your IMAP provider by a secured or non-secured connection.</_description>
+    </key>
+    <key name="attachment-size" type="i">
+      <default>20</default>
+      <_summary>Email-attachment size specified in MB</_summary>
+      <_description>The email-attachment size to use. Must not be greater than the maximum size your IMAP provider does accept.</_description>
+    </key>
+    <key name="mailbox" type="s">
+      <default>''</default>
+      <_summary>The mailbox you want to use (A Mailbox is usually presented as a folder)</_summary>
+      <_description>Allows you to specify a different mailbox. The default is "INBOX". Other languages may require a different mailbox than the default.</_description>
+    </key>
+    <key name="from-address-prefix" type="s">
+      <!-- Translators: Do not translate the default value -->
+      <default>'Deja-Dup-Backup'</default>
+      <_summary>'The "From" address of your backup'</_summary>
+      <_description>The text will be used as the "From" address in the IMAP server. Then on a restore (or list) command the from-address-prefix will distinguish between different backups.</_description>
+    </key>
+  </schema>
   <schema id="org.gnome.DejaDup.File" path="/org/gnome/deja-dup/file/">
     <key name="path" type="s">
       <default>''</default>

=== modified file 'help/translations/deja-dup-help.pot'
--- help/translations/deja-dup-help.pot	2011-01-10 02:52:47 +0000
+++ help/translations/deja-dup-help.pot	2011-01-14 10:52:53 +0000
@@ -1,7 +1,11 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
+<<<<<<< TREE
 "POT-Creation-Date: 2011-01-09 21:51-0500\n"
+=======
+"POT-Creation-Date: 2011-01-07 09:30+0100\n"
+>>>>>>> MERGE-SOURCE
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@xxxxxx>\n"

=== modified file 'po/POTFILES.in'
--- po/POTFILES.in	2010-12-29 18:29:25 +0000
+++ po/POTFILES.in	2011-01-14 10:52:53 +0000
@@ -13,6 +13,8 @@
 common/BackendFile.vala
 common/BackendRackspace.vala
 common/BackendS3.vala
+common/BackendIMAP.vala
+common/IMAP_Configuration_Helper.vala
 common/BackendU1.vala
 common/Backend.vala
 common/CommonUtils.vala
@@ -58,6 +60,7 @@
 widgets/ConfigLocationFile.vala
 widgets/ConfigLocationRackspace.vala
 widgets/ConfigLocationS3.vala
+widgets/ConfigLocationIMAP.vala
 widgets/ConfigLocationSMB.vala
 widgets/ConfigLocationSSH.vala
 widgets/ConfigLocationTable.vala

=== modified file 'po/POTFILES.skip'
--- po/POTFILES.skip	2010-12-29 18:29:25 +0000
+++ po/POTFILES.skip	2011-01-14 10:52:53 +0000
@@ -2,6 +2,8 @@
 common/BackendFile.c
 common/BackendRackspace.c
 common/BackendS3.c
+common/BackendIMAP.c
+common/IMAP_Configuration_Helper.c
 common/BackendU1.c
 common/Backend.c
 common/CommonUtils.c
@@ -47,6 +49,7 @@
 widgets/ConfigLocationFile.c
 widgets/ConfigLocationRackspace.c
 widgets/ConfigLocationS3.c
+widgets/ConfigLocationIMAP.c
 widgets/ConfigLocationSMB.c
 widgets/ConfigLocationSSH.c
 widgets/ConfigLocationTable.c

=== renamed file 'po/deja-dup.pot' => 'po/deja-dup.pot.THIS'
=== modified file 'widgets/ConfigBool.vala'
--- widgets/ConfigBool.vala	2010-12-23 01:23:54 +0000
+++ widgets/ConfigBool.vala	2011-01-14 10:52:53 +0000
@@ -32,7 +32,7 @@
   
   public bool get_active() {return button.get_active();}
   
-  protected Gtk.CheckButton button;
+  public Gtk.CheckButton button { get; private set; }
   protected bool user_driven = true;
   construct {
     button = new Gtk.CheckButton.with_mnemonic(label);

=== modified file 'widgets/ConfigEntry.vala'
--- widgets/ConfigEntry.vala	2011-01-05 23:44:57 +0000
+++ widgets/ConfigEntry.vala	2011-01-14 10:52:53 +0000
@@ -33,7 +33,7 @@
     return entry.get_text();
   }
 
-  protected Gtk.Entry entry;
+  public Gtk.Entry entry { get; private set; }
   construct {
     entry = new Gtk.Entry();
     add(entry);
@@ -60,6 +60,7 @@
     write_to_config();
     return false;
   }
+
 }
 
 }

=== modified file 'widgets/ConfigLabelLocation.vala'
--- widgets/ConfigLabelLocation.vala	2010-12-26 19:13:56 +0000
+++ widgets/ConfigLabelLocation.vala	2011-01-14 10:52:53 +0000
@@ -38,6 +38,7 @@
     watch_key(null, DejaDup.get_settings(FILE_ROOT));
     watch_key(null, DejaDup.get_settings(S3_ROOT));
     watch_key(null, DejaDup.get_settings(U1_ROOT));
+    watch_key(null, DejaDup.get_settings(IMAP_ROOT));
     watch_key(null, DejaDup.get_settings(RACKSPACE_ROOT));
     set_from_config();
   }

=== modified file 'widgets/ConfigLocation.vala'
--- widgets/ConfigLocation.vala	2010-12-30 05:58:09 +0000
+++ widgets/ConfigLocation.vala	2011-01-14 10:52:53 +0000
@@ -50,6 +50,7 @@
   int index_ftp;
   int index_dav;
   int index_s3;
+  int index_imap;
   int index_rackspace;
   int index_u1 = -2;
   int index_ssh;
@@ -99,6 +100,10 @@
     // Insert cloud providers
     index_s3 = add_entry(i++, new ThemedIcon("deja-dup-cloud"),
                          _("Amazon S3"), 0, new ConfigLocationS3(label_sizes));
+
+    index_imap = add_entry(i++, new ThemedIcon("deja-dup-cloud"),
+                           _("Email service providing IMAP access"), 0, new ConfigLocationIMAP(label_sizes));
+
     index_rackspace = add_entry(i++, new ThemedIcon("deja-dup-cloud"),
                                 _("Rackspace Cloud Files"), 0,
                                 new ConfigLocationRackspace(label_sizes));
@@ -252,6 +257,8 @@
     var backend = Backend.get_default_type();
     if (backend == "s3")
       index = index_s3;
+    else if (backend == "imap")
+      index = index_imap;
     else if (backend == "rackspace")
       index = index_rackspace;
     else if (backend == "u1")
@@ -323,6 +330,8 @@
 
     if (index == index_s3)
       settings.set_string(BACKEND_KEY, "s3");
+    if (index == index_imap)
+      settings.set_string(BACKEND_KEY, "imap");
     else if (index == index_rackspace)
       settings.set_string(BACKEND_KEY, "rackspace");
     else if (index == index_u1)

=== added file 'widgets/ConfigLocationIMAP.vala'
--- widgets/ConfigLocationIMAP.vala	1970-01-01 00:00:00 +0000
+++ widgets/ConfigLocationIMAP.vala	2011-01-14 10:52:53 +0000
@@ -0,0 +1,77 @@
+/* -*- Mode: Vala; indent-tabs-mode: nil; tab-width: 2 -*- */
+/*
+    This file is part of Déjà Dup.
+    © 2011 Lars Jegenhorst <dev.lars@xxxxxxxxxxxxx>
+
+    Déjà Dup is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    Déjà Dup is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with Déjà Dup.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+using GLib;
+
+namespace DejaDup {
+
+public class ConfigLocationIMAP : ConfigLocationTable
+{
+  public ConfigLocationIMAP(Gtk.SizeGroup sg) {
+    Object(label_sizes: sg);
+  }
+
+  ConfigEntry server_widget = null;
+  ConfigEntry email_widget = null;
+  ConfigNumber attachment_size_widget = null;
+  ConfigBool use_secure_connection_widget = null;
+  const int MAX_ATTACHMENT_SIZE = 100; // specified in MB
+
+  construct {
+    email_widget = new ConfigEntry(DejaDup.IMAP_EMAIL_ADDRESS, DejaDup.IMAP_ROOT);
+    email_widget.entry.changed.connect (() => this.on_email_changed());
+    add_widget(_("_Email address:"), email_widget);
+
+    server_widget = new ConfigEntry(DejaDup.IMAP_SERVER, DejaDup.IMAP_ROOT);
+    add_widget(_("_IMAP server address:"), server_widget);
+    use_secure_connection_widget = new ConfigBool(DejaDup.IMAP_USE_IMAPS, _("_Use secure connection"), DejaDup.IMAP_ROOT);
+    add_widget(_("_Use secure connection (IMAPS):"), use_secure_connection_widget);
+    attachment_size_widget = new ConfigNumber(DejaDup.IMAP_ATTACHMENT_SIZE, 1, 100, DejaDup.IMAP_ROOT);
+    // TODO Warn the user not to exceed the maximum size his IMAP provider does accept. 
+    add_widget(_("_Email-attachment size (MB):"), attachment_size_widget);
+    add_optional_label();
+    add_widget(_("_Mailbox (usually presented as folders):"), new ConfigEntry(DejaDup.IMAP_MAILBOX, DejaDup.IMAP_ROOT));
+    // add_widget(_("_The from address of generated emails:"), new ConfigEntry(DejaDup.IMAP_FROM_ADDRESS_PREFIX, DejaDup.IMAP_ROOT));
+    on_email_changed();
+  }
+
+
+  public void on_email_changed() {
+    try {
+      IMAP_Provider provider = IMAP_Configuration_Helper.getInstance().get_imap_provider_details(email_widget.entry.text);
+      if (provider != null) {
+        server_widget.entry.text = provider.imap_server_address;
+        server_widget.entry.set_sensitive(false);
+        if (attachment_size_widget.spin.value > provider.maximum_attachment_size)
+          attachment_size_widget.spin.value = provider.maximum_attachment_size;
+        attachment_size_widget.spin.set_range(0, provider.maximum_attachment_size);
+        use_secure_connection_widget.button.set_active(provider.use_imaps);
+        use_secure_connection_widget.button.set_sensitive(false);
+      } else { 
+        server_widget.entry.set_sensitive(true);
+        use_secure_connection_widget.button.set_sensitive(true);
+        attachment_size_widget.spin.set_range(0, MAX_ATTACHMENT_SIZE);
+      }
+    } catch (RegexError ex) {}
+  }
+
+}
+
+} // Namespace
+

=== modified file 'widgets/ConfigNumber.vala'
--- widgets/ConfigNumber.vala	2010-10-03 05:24:54 +0000
+++ widgets/ConfigNumber.vala	2011-01-14 10:52:53 +0000
@@ -31,7 +31,7 @@
     Object(key: key, lower_bound: lower_bound, upper_bound: upper_bound, ns: ns);
   }
   
-  Gtk.SpinButton spin;
+  public Gtk.SpinButton spin {get; private set;}
   construct {
     spin = new Gtk.SpinButton.with_range(lower_bound, upper_bound, 1);
     add(spin);

=== modified file 'widgets/Makefile.am'
--- widgets/Makefile.am	2010-12-29 18:29:25 +0000
+++ widgets/Makefile.am	2011-01-14 10:52:53 +0000
@@ -47,6 +47,7 @@
 	ConfigLocationRackspace.vala \
 	ConfigLocationS3.vala \
 	ConfigLocationSSH.vala \
+	ConfigLocationIMAP.vala \
 	ConfigLocationSMB.vala \
 	ConfigLocationTable.vala \
 	ConfigLocationU1.vala \

=== modified file 'widgets/WidgetUtils.vala'
--- widgets/WidgetUtils.vala	2010-12-30 03:56:30 +0000
+++ widgets/WidgetUtils.vala	2011-01-14 10:52:53 +0000
@@ -36,6 +36,7 @@
 
 // These need to be namespace-wide to prevent an odd compiler syntax error.
 const string[] authors = {"Andrew Fister <temposs@xxxxxxxxx>",
+                          "Lars Jegenhorst <dev.lars@xxxxxxxxxxxxx>",
                           "Michael Terry <mike@xxxxxxxxxxx>",
                           "Michael Vogt <michael.vogt@xxxxxxxxxx>",
                           "Urban Skudnik <urban.skudnik@xxxxxxxxx>",


Follow ups