Support Outlook.com IMAP: Closes #7479
This takes advantage of Outlook.com's new IMAP support, meaning Geary works with Outlook.com, Hotmail, and Live.com users. Because Outlook.com doesn't support UIDPLUS, some features (in particular, draft auto-save) is unavailable, as is the ability to use its Archive folder directly. This patch fixes a couple of bugs that occur when a server doesn't support UIDPLUS. Also fixes a use case with UID increment/decrement that caused a flag watcher bug due to ImapDB.Folder always returning the same email if only one was present in the folder.
This commit is contained in:
parent
94861a0bef
commit
c8b4f9e0e2
15 changed files with 242 additions and 47 deletions
|
|
@ -201,6 +201,8 @@ engine/imap-engine/gmail/imap-engine-gmail-folder.vala
|
|||
engine/imap-engine/gmail/imap-engine-gmail-search-folder.vala
|
||||
engine/imap-engine/other/imap-engine-other-account.vala
|
||||
engine/imap-engine/other/imap-engine-other-folder.vala
|
||||
engine/imap-engine/outlook/imap-engine-outlook-account.vala
|
||||
engine/imap-engine/outlook/imap-engine-outlook-folder.vala
|
||||
engine/imap-engine/replay-ops/imap-engine-abstract-list-email.vala
|
||||
engine/imap-engine/replay-ops/imap-engine-copy-email.vala
|
||||
engine/imap-engine/replay-ops/imap-engine-create-email.vala
|
||||
|
|
|
|||
|
|
@ -497,7 +497,7 @@ public class AddEditPage : Gtk.Box {
|
|||
return false;
|
||||
break;
|
||||
|
||||
// GMAIL and YAHOO
|
||||
// GMAIL, YAHOO, and OUTLOOK
|
||||
default:
|
||||
if (Geary.String.is_empty_or_whitespace(nickname) ||
|
||||
Geary.String.is_empty_or_whitespace(email_address) ||
|
||||
|
|
|
|||
|
|
@ -21,13 +21,21 @@ public class Geary.AccountInformation : BaseObject {
|
|||
private const string IMAP_PORT = "imap_port";
|
||||
private const string IMAP_SSL = "imap_ssl";
|
||||
private const string IMAP_STARTTLS = "imap_starttls";
|
||||
private const string IMAP_PIPELINE = "imap_pipeline";
|
||||
private const string SMTP_HOST = "smtp_host";
|
||||
private const string SMTP_PORT = "smtp_port";
|
||||
private const string SMTP_SSL = "smtp_ssl";
|
||||
private const string SMTP_STARTTLS = "smtp_starttls";
|
||||
private const string SMTP_NOAUTH = "smtp_noauth";
|
||||
|
||||
|
||||
//
|
||||
// "Retired" keys
|
||||
//
|
||||
|
||||
/*
|
||||
* key: "imap_pipeline"
|
||||
* value: bool
|
||||
*/
|
||||
|
||||
public const string SETTINGS_FILENAME = "geary.ini";
|
||||
public const int DEFAULT_PREFETCH_PERIOD_DAYS = 14;
|
||||
|
||||
|
|
@ -42,7 +50,6 @@ public class Geary.AccountInformation : BaseObject {
|
|||
public string nickname { get; set; }
|
||||
public string email { get; set; }
|
||||
public Geary.ServiceProvider service_provider { get; set; }
|
||||
public bool imap_server_pipeline { get; set; default = true; }
|
||||
public int prefetch_period_days { get; set; }
|
||||
|
||||
// Order for display purposes.
|
||||
|
|
@ -98,8 +105,6 @@ public class Geary.AccountInformation : BaseObject {
|
|||
if (ordinal >= default_ordinal)
|
||||
default_ordinal = ordinal + 1;
|
||||
|
||||
imap_server_pipeline = get_bool_value(key_file, GROUP, IMAP_PIPELINE, true);
|
||||
|
||||
if (service_provider == ServiceProvider.OTHER) {
|
||||
default_imap_server_host = get_string_value(key_file, GROUP, IMAP_HOST);
|
||||
default_imap_server_port = get_uint16_value(key_file, GROUP, IMAP_PORT,
|
||||
|
|
@ -120,11 +125,6 @@ public class Geary.AccountInformation : BaseObject {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// currently IMAP pipelining is *always* turned off with generic servers; see
|
||||
// http://redmine.yorba.org/issues/5224
|
||||
if (service_provider == Geary.ServiceProvider.OTHER)
|
||||
imap_server_pipeline = false;
|
||||
}
|
||||
|
||||
// Copies all data from the "from" object into this one.
|
||||
|
|
@ -133,7 +133,6 @@ public class Geary.AccountInformation : BaseObject {
|
|||
nickname = from.nickname;
|
||||
email = from.email;
|
||||
service_provider = from.service_provider;
|
||||
imap_server_pipeline = from.imap_server_pipeline;
|
||||
prefetch_period_days = from.prefetch_period_days;
|
||||
ordinal = from.ordinal;
|
||||
default_imap_server_host = from.default_imap_server_host;
|
||||
|
|
@ -313,6 +312,9 @@ public class Geary.AccountInformation : BaseObject {
|
|||
case ServiceProvider.YAHOO:
|
||||
return ImapEngine.YahooAccount.IMAP_ENDPOINT;
|
||||
|
||||
case ServiceProvider.OUTLOOK:
|
||||
return ImapEngine.OutlookAccount.IMAP_ENDPOINT;
|
||||
|
||||
case ServiceProvider.OTHER:
|
||||
Endpoint.Flags imap_flags = Endpoint.Flags.GRACEFUL_DISCONNECT;
|
||||
if (default_imap_server_ssl)
|
||||
|
|
@ -336,6 +338,9 @@ public class Geary.AccountInformation : BaseObject {
|
|||
case ServiceProvider.YAHOO:
|
||||
return ImapEngine.YahooAccount.SMTP_ENDPOINT;
|
||||
|
||||
case ServiceProvider.OUTLOOK:
|
||||
return ImapEngine.OutlookAccount.SMTP_ENDPOINT;
|
||||
|
||||
case ServiceProvider.OTHER:
|
||||
Endpoint.Flags smtp_flags = Endpoint.Flags.GRACEFUL_DISCONNECT;
|
||||
if (default_smtp_server_ssl)
|
||||
|
|
@ -421,8 +426,6 @@ public class Geary.AccountInformation : BaseObject {
|
|||
key_file.set_boolean(GROUP, SMTP_REMEMBER_PASSWORD_KEY, smtp_remember_password);
|
||||
key_file.set_integer(GROUP, PREFETCH_PERIOD_DAYS_KEY, prefetch_period_days);
|
||||
|
||||
key_file.set_boolean(GROUP, IMAP_PIPELINE, imap_server_pipeline);
|
||||
|
||||
if (service_provider == ServiceProvider.OTHER) {
|
||||
key_file.set_value(GROUP, IMAP_HOST, default_imap_server_host);
|
||||
key_file.set_integer(GROUP, IMAP_PORT, default_imap_server_port);
|
||||
|
|
|
|||
|
|
@ -322,6 +322,11 @@ public class Geary.Engine : BaseObject {
|
|||
account_information, remote_account, local_account);
|
||||
break;
|
||||
|
||||
case ServiceProvider.OUTLOOK:
|
||||
account = new ImapEngine.OutlookAccount("Outlook:%s".printf(account_information.email),
|
||||
account_information, remote_account, local_account);
|
||||
break;
|
||||
|
||||
case ServiceProvider.OTHER:
|
||||
account = new ImapEngine.OtherAccount("Other:%s".printf(account_information.email),
|
||||
account_information, remote_account, local_account);
|
||||
|
|
|
|||
|
|
@ -4,15 +4,25 @@
|
|||
* (version 2.1 or later). See the COPYING file in this distribution.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A representation of the various built-in email service providers Geary supports.
|
||||
*/
|
||||
|
||||
public enum Geary.ServiceProvider {
|
||||
GMAIL,
|
||||
YAHOO,
|
||||
OUTLOOK,
|
||||
OTHER;
|
||||
|
||||
public static ServiceProvider[] get_providers() {
|
||||
return { GMAIL, YAHOO, OTHER };
|
||||
return { GMAIL, YAHOO, OUTLOOK, OTHER };
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the service provider in a serialized form.
|
||||
*
|
||||
* @see from_string
|
||||
*/
|
||||
public string to_string() {
|
||||
switch (this) {
|
||||
case GMAIL:
|
||||
|
|
@ -21,6 +31,9 @@ public enum Geary.ServiceProvider {
|
|||
case YAHOO:
|
||||
return "YAHOO";
|
||||
|
||||
case OUTLOOK:
|
||||
return "OUTLOOK";
|
||||
|
||||
case OTHER:
|
||||
return "OTHER";
|
||||
|
||||
|
|
@ -29,6 +42,10 @@ public enum Geary.ServiceProvider {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the service provider's name in a translated UTF-8 string suitable for display to the
|
||||
* user.
|
||||
*/
|
||||
public string display_name() {
|
||||
switch (this) {
|
||||
case GMAIL:
|
||||
|
|
@ -37,6 +54,9 @@ public enum Geary.ServiceProvider {
|
|||
case YAHOO:
|
||||
return _("Yahoo! Mail");
|
||||
|
||||
case OUTLOOK:
|
||||
return _("Outlook.com");
|
||||
|
||||
case OTHER:
|
||||
return _("Other");
|
||||
|
||||
|
|
@ -45,6 +65,12 @@ public enum Geary.ServiceProvider {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a string form of the service provider (returned by {@link to_string} to a
|
||||
* {@link ServiceProvider} value.
|
||||
*
|
||||
* @see to_string
|
||||
*/
|
||||
public static ServiceProvider from_string(string str) {
|
||||
switch (str.up()) {
|
||||
case "GMAIL":
|
||||
|
|
@ -53,6 +79,9 @@ public enum Geary.ServiceProvider {
|
|||
case "YAHOO":
|
||||
return YAHOO;
|
||||
|
||||
case "OUTLOOK":
|
||||
return OUTLOOK;
|
||||
|
||||
case "OTHER":
|
||||
return OTHER;
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,8 @@ public enum Geary.SpecialFolderType {
|
|||
ALL_MAIL,
|
||||
SPAM,
|
||||
TRASH,
|
||||
OUTBOX;
|
||||
OUTBOX,
|
||||
ARCHIVE;
|
||||
|
||||
public unowned string get_display_name() {
|
||||
switch (this) {
|
||||
|
|
@ -49,6 +50,9 @@ public enum Geary.SpecialFolderType {
|
|||
case SEARCH:
|
||||
return _("Search");
|
||||
|
||||
case ARCHIVE:
|
||||
return _("Archive");
|
||||
|
||||
case NONE:
|
||||
default:
|
||||
return _("None");
|
||||
|
|
|
|||
|
|
@ -251,9 +251,9 @@ private class Geary.ImapDB.Folder : BaseObject, Geary.ReferenceSemantics {
|
|||
// deal with exclusive searches
|
||||
if (!including_id) {
|
||||
if (oldest_to_newest)
|
||||
start_uid = start_uid.next();
|
||||
start_uid = start_uid.next(false);
|
||||
else
|
||||
start_uid = start_uid.previous();
|
||||
start_uid = start_uid.previous(false);
|
||||
}
|
||||
} else if (oldest_to_newest) {
|
||||
start_uid = new Imap.UID(Imap.UID.MIN);
|
||||
|
|
@ -261,6 +261,9 @@ private class Geary.ImapDB.Folder : BaseObject, Geary.ReferenceSemantics {
|
|||
start_uid = new Imap.UID(Imap.UID.MAX);
|
||||
}
|
||||
|
||||
if (!start_uid.is_valid())
|
||||
return Db.TransactionOutcome.DONE;
|
||||
|
||||
StringBuilder sql = new StringBuilder("""
|
||||
SELECT MessageLocationTable.message_id, ordering, remove_marker
|
||||
FROM MessageLocationTable
|
||||
|
|
@ -332,11 +335,11 @@ private class Geary.ImapDB.Folder : BaseObject, Geary.ReferenceSemantics {
|
|||
Imap.UID end_uid = end_location.uid;
|
||||
|
||||
if (!including_id) {
|
||||
start_uid = start_uid.next();
|
||||
end_uid = end_uid.previous();
|
||||
start_uid = start_uid.next(false);
|
||||
end_uid = end_uid.previous(false);
|
||||
}
|
||||
|
||||
if (start_uid.compare_to(end_uid) > 0)
|
||||
if (!start_uid.is_valid() || !end_uid.is_valid() || start_uid.compare_to(end_uid) > 0)
|
||||
return Db.TransactionOutcome.DONE;
|
||||
|
||||
Db.Statement stmt = cx.prepare("""
|
||||
|
|
@ -369,11 +372,11 @@ private class Geary.ImapDB.Folder : BaseObject, Geary.ReferenceSemantics {
|
|||
Imap.UID end_uid = end;
|
||||
|
||||
if (!including_id) {
|
||||
start_uid = start_uid.next();
|
||||
end_uid = end_uid.previous();
|
||||
start_uid = start_uid.next(false);
|
||||
end_uid = end_uid.previous(false);
|
||||
}
|
||||
|
||||
if (start_uid.compare_to(end_uid) > 0)
|
||||
if (!start_uid.is_valid() || !end_uid.is_valid() || start_uid.compare_to(end_uid) > 0)
|
||||
return null;
|
||||
|
||||
// Break up work so all reading isn't done in single transaction that locks up the
|
||||
|
|
|
|||
|
|
@ -184,7 +184,7 @@ private class Geary.ImapEngine.GenericFolder : Geary.AbstractFolder, Geary.Folde
|
|||
|
||||
// a full normalize works from the highest possible UID on the remote and work down to the lowest UID on
|
||||
// the local; this covers all messages appended since last seen as well as any removed
|
||||
Imap.UID last_uid = remote_properties.uid_next.previous();
|
||||
Imap.UID last_uid = remote_properties.uid_next.previous(true);
|
||||
|
||||
// if the difference in UIDNEXT values equals the difference in message count, then only
|
||||
// an append could have happened, so only pull in the new messages ... note that this is not foolproof,
|
||||
|
|
@ -195,7 +195,7 @@ private class Geary.ImapEngine.GenericFolder : Geary.AbstractFolder, Geary.Folde
|
|||
// situation, esp. messages being removed.)
|
||||
Imap.UID first_uid;
|
||||
if (!is_dirty && uidnext_diff == (remote_message_count - local_message_count)) {
|
||||
first_uid = local_latest_id.uid.next();
|
||||
first_uid = local_latest_id.uid.next(true);
|
||||
|
||||
debug("%s: Messages only appended (local/remote UIDNEXT=%s/%s total=%d/%d diff=%s), gathering mail UIDs %s:%s",
|
||||
to_string(), local_properties.uid_next.to_string(), remote_properties.uid_next.to_string(),
|
||||
|
|
@ -1142,7 +1142,7 @@ private class Geary.ImapEngine.GenericFolder : Geary.AbstractFolder, Geary.Folde
|
|||
}
|
||||
|
||||
criteria.and(Imap.SearchCriterion.message_set(
|
||||
new Imap.MessageSet.uid_range(new Imap.UID(Imap.UID.MIN), before_uid.previous())));
|
||||
new Imap.MessageSet.uid_range(new Imap.UID(Imap.UID.MIN), before_uid.previous(true))));
|
||||
}
|
||||
|
||||
Gee.List<Geary.Email> accumulator = new Gee.ArrayList<Geary.Email>();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,68 @@
|
|||
/* Copyright 2013 Yorba Foundation
|
||||
*
|
||||
* This software is licensed under the GNU Lesser General Public License
|
||||
* (version 2.1 or later). See the COPYING file in this distribution.
|
||||
*/
|
||||
|
||||
private class Geary.ImapEngine.OutlookAccount : Geary.ImapEngine.GenericAccount {
|
||||
private static Geary.Endpoint? _imap_endpoint = null;
|
||||
public static Geary.Endpoint IMAP_ENDPOINT { get {
|
||||
if (_imap_endpoint == null) {
|
||||
_imap_endpoint = new Geary.Endpoint(
|
||||
"imap-mail.outlook.com",
|
||||
Imap.ClientConnection.DEFAULT_PORT_SSL,
|
||||
Geary.Endpoint.Flags.SSL | Geary.Endpoint.Flags.GRACEFUL_DISCONNECT,
|
||||
Imap.ClientConnection.RECOMMENDED_TIMEOUT_SEC);
|
||||
}
|
||||
|
||||
return _imap_endpoint;
|
||||
} }
|
||||
|
||||
private static Geary.Endpoint? _smtp_endpoint = null;
|
||||
public static Geary.Endpoint SMTP_ENDPOINT { get {
|
||||
if (_smtp_endpoint == null) {
|
||||
_smtp_endpoint = new Geary.Endpoint(
|
||||
"smtp-mail.outlook.com",
|
||||
Smtp.ClientConnection.DEFAULT_PORT_STARTTLS,
|
||||
Geary.Endpoint.Flags.STARTTLS | Geary.Endpoint.Flags.GRACEFUL_DISCONNECT,
|
||||
Smtp.ClientConnection.DEFAULT_TIMEOUT_SEC);
|
||||
}
|
||||
|
||||
return _smtp_endpoint;
|
||||
} }
|
||||
|
||||
public OutlookAccount(string name, AccountInformation account_information, Imap.Account remote,
|
||||
ImapDB.Account local) {
|
||||
base (name, account_information, remote, local);
|
||||
}
|
||||
|
||||
protected override GenericFolder new_folder(Geary.FolderPath path, Imap.Account remote_account,
|
||||
ImapDB.Account local_account, ImapDB.Folder local_folder) {
|
||||
// use the Folder's attributes to determine if it's a special folder type, unless it's
|
||||
// INBOX; that's determined by name
|
||||
SpecialFolderType special_folder_type;
|
||||
if (Imap.MailboxSpecifier.folder_path_is_inbox(path))
|
||||
special_folder_type = SpecialFolderType.INBOX;
|
||||
else
|
||||
special_folder_type = local_folder.get_properties().attrs.get_special_folder_type();
|
||||
|
||||
// generate properly-interfaced Folder depending on the special type
|
||||
// Proper Drafts support depends on Outlook.com supporting UIDPLUS or us devising another
|
||||
// mechanism to associate new messages with drafts-in-progress; see
|
||||
// http://redmine.yorba.org/issues/7495
|
||||
switch (special_folder_type) {
|
||||
case SpecialFolderType.SENT:
|
||||
return new GenericSentMailFolder(this, remote_account, local_account, local_folder,
|
||||
special_folder_type);
|
||||
|
||||
case SpecialFolderType.TRASH:
|
||||
return new GenericTrashFolder(this, remote_account, local_account, local_folder,
|
||||
special_folder_type);
|
||||
|
||||
default:
|
||||
return new OutlookFolder(this, remote_account, local_account, local_folder,
|
||||
special_folder_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
/* Copyright 2013 Yorba Foundation
|
||||
*
|
||||
* This software is licensed under the GNU Lesser General Public License
|
||||
* (version 2.1 or later). See the COPYING file in this distribution.
|
||||
*/
|
||||
|
||||
private class Geary.ImapEngine.OutlookFolder : GenericFolder, Geary.FolderSupport.Remove {
|
||||
public OutlookFolder(OutlookAccount account, Imap.Account remote, ImapDB.Account local,
|
||||
ImapDB.Folder local_folder, SpecialFolderType special_folder_type) {
|
||||
base (account, remote, local, local_folder, special_folder_type);
|
||||
}
|
||||
|
||||
public async void remove_email_async(Gee.List<Geary.EmailIdentifier> email_ids,
|
||||
Cancellable? cancellable = null) throws Error {
|
||||
yield expunge_email_async(email_ids, cancellable);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -506,7 +506,7 @@ private class Geary.Imap.Folder : BaseObject {
|
|||
StoreCommand store_cmd = new StoreCommand(msg_set, flags, true, false);
|
||||
cmds.add(store_cmd);
|
||||
|
||||
if (session.capabilities.has_capability(Capabilities.UIDPLUS))
|
||||
if (msg_set.is_uid && session.capabilities.supports_uidplus())
|
||||
cmds.add(new ExpungeCommand.uid(msg_set));
|
||||
else
|
||||
cmds.add(new ExpungeCommand());
|
||||
|
|
@ -564,7 +564,7 @@ private class Geary.Imap.Folder : BaseObject {
|
|||
flags.add(MessageFlag.DELETED);
|
||||
cmds.add(new StoreCommand(msg_set, flags, true, false));
|
||||
|
||||
if (msg_set.is_uid)
|
||||
if (msg_set.is_uid && session.capabilities.supports_uidplus())
|
||||
cmds.add(new ExpungeCommand.uid(msg_set));
|
||||
else
|
||||
cmds.add(new ExpungeCommand());
|
||||
|
|
|
|||
|
|
@ -32,29 +32,33 @@ public class Geary.Imap.UID : Geary.MessageData.Int64MessageData, Geary.Imap.Mes
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a valid UID, which means returning MIN or MAX if the value is out of range (either
|
||||
* direction) or MAX if this value is already MAX.
|
||||
* Returns the UID logically next (or after) this one.
|
||||
*
|
||||
* If clamped this always returns a valid UID, which means returning MIN or MAX if
|
||||
* the value is out of range (either direction) or MAX if this value is already MAX.
|
||||
*
|
||||
* Otherwise, it may return an invalid UID and should be verified before using.
|
||||
*
|
||||
* @see previous
|
||||
* @see is_valid
|
||||
*/
|
||||
public UID next() {
|
||||
if (value < MIN)
|
||||
return new UID(MIN);
|
||||
else if (value > MAX)
|
||||
return new UID(MAX);
|
||||
else
|
||||
return new UID(Numeric.int64_ceiling(value + 1, MAX));
|
||||
public UID next(bool clamped) {
|
||||
return clamped ? new UID((value + 1).clamp(MIN, MAX)) : new UID(value + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a valid UID, which means returning MIN or MAX if the value is out of range (either
|
||||
* direction) or MIN if this value is already MIN.
|
||||
* Returns the UID logically previous (or before) this one.
|
||||
*
|
||||
* If clamped this always returns a valid UID, which means returning MIN or MAX if
|
||||
* the value is out of range (either direction) or MIN if this value is already MIN.
|
||||
*
|
||||
* Otherwise, it may return a UID where {@link is_valid} returns false.
|
||||
*
|
||||
* @see next
|
||||
* @see is_valid
|
||||
*/
|
||||
public UID previous() {
|
||||
if (value < MIN)
|
||||
return new UID(MIN);
|
||||
else if (value > MAX)
|
||||
return new UID(MAX);
|
||||
else
|
||||
return new UID(Numeric.int64_floor(value - 1, MIN));
|
||||
public UID previous(bool clamped) {
|
||||
return clamped ? new UID((value - 1).clamp(MIN, MAX)) : new UID(value - 1);
|
||||
}
|
||||
|
||||
public virtual int compare_to(Geary.Imap.UID other) {
|
||||
|
|
|
|||
|
|
@ -35,5 +35,23 @@ public class Geary.Imap.Capabilities : Geary.GenericCapabilities {
|
|||
public override string to_string() {
|
||||
return "#%d: %s".printf(revision, base.to_string());
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates the {@link ClientSession} reported support for IDLE.
|
||||
*
|
||||
* See [[https://tools.ietf.org/html/rfc2177]]
|
||||
*/
|
||||
public bool supports_idle() {
|
||||
return has_capability(IDLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates the {@link ClientSession} reported support for UIDPLUS.
|
||||
*
|
||||
* See [[https://tools.ietf.org/html/rfc4315]]
|
||||
*/
|
||||
public bool supports_uidplus() {
|
||||
return has_capability(UIDPLUS);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -134,6 +134,30 @@ public class Geary.Imap.MailboxAttribute : Geary.Imap.Flag {
|
|||
return _xlist_important;
|
||||
} }
|
||||
|
||||
private static MailboxAttribute? _special_use_all = null;
|
||||
public static MailboxAttribute SPECIAL_FOLDER_ALL { get {
|
||||
return (_special_use_all != null) ? _special_use_all
|
||||
: _special_use_all = new MailboxAttribute("\\All");
|
||||
} }
|
||||
|
||||
private static MailboxAttribute? _special_use_archive = null;
|
||||
public static MailboxAttribute SPECIAL_FOLDER_ARCHIVE { get {
|
||||
return (_special_use_archive != null) ? _special_use_archive
|
||||
: _special_use_archive = new MailboxAttribute("\\Archive");
|
||||
} }
|
||||
|
||||
private static MailboxAttribute? _special_use_flagged = null;
|
||||
public static MailboxAttribute SPECIAL_FOLDER_FLAGGED { get {
|
||||
return (_special_use_flagged != null) ? _special_use_flagged
|
||||
: _special_use_flagged = new MailboxAttribute("\\Flagged");
|
||||
} }
|
||||
|
||||
private static MailboxAttribute? _special_use_junk = null;
|
||||
public static MailboxAttribute SPECIAL_FOLDER_JUNK { get {
|
||||
return (_special_use_junk != null) ? _special_use_junk
|
||||
: _special_use_junk = new MailboxAttribute("\\Junk");
|
||||
} }
|
||||
|
||||
public MailboxAttribute(string value) {
|
||||
base (value);
|
||||
}
|
||||
|
|
@ -155,6 +179,10 @@ public class Geary.Imap.MailboxAttribute : Geary.Imap.Flag {
|
|||
to_init = SPECIAL_FOLDER_SPAM;
|
||||
to_init = SPECIAL_FOLDER_STARRED;
|
||||
to_init = SPECIAL_FOLDER_TRASH;
|
||||
to_init = SPECIAL_FOLDER_ALL;
|
||||
to_init = SPECIAL_FOLDER_ARCHIVE;
|
||||
to_init = SPECIAL_FOLDER_FLAGGED;
|
||||
to_init = SPECIAL_FOLDER_JUNK;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -72,6 +72,19 @@ public class Geary.Imap.MailboxAttributes : Geary.Imap.Flags {
|
|||
if (contains(MailboxAttribute.SPECIAL_FOLDER_IMPORTANT))
|
||||
return Geary.SpecialFolderType.IMPORTANT;
|
||||
|
||||
if (contains(MailboxAttribute.SPECIAL_FOLDER_ALL))
|
||||
return Geary.SpecialFolderType.ALL_MAIL;
|
||||
|
||||
// TODO: Convert into SpecialFolderType.ARCHIVE (to support services that have an Archive
|
||||
// folder that isn't an All Mail folder, i.e. Outlook.com):
|
||||
// http://redmine.yorba.org/issues/7492
|
||||
|
||||
if (contains(MailboxAttribute.SPECIAL_FOLDER_FLAGGED))
|
||||
return Geary.SpecialFolderType.FLAGGED;
|
||||
|
||||
if (contains(MailboxAttribute.SPECIAL_FOLDER_JUNK))
|
||||
return Geary.SpecialFolderType.SPAM;
|
||||
|
||||
return Geary.SpecialFolderType.NONE;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue