Class: Imap::Providers::Gmail
Overview
Gmail has a special header for both labels (X-GM-LABELS) and their threading system (X-GM-THRID). We need to monkey-patch Net::IMAP to get access to these. Also the archiving functionality is custom, all UIDs in a thread must have the \Inbox label removed.
Constant Summary
collapse
- X_GM_LABELS =
"X-GM-LABELS"
- X_GM_THRID =
"X-GM-THRID"
Instance Method Summary
collapse
Methods inherited from Generic
#account_digest, #can?, #connect!, #disconnect!, #disconnected?, #find_spam_by_message_ids, #find_trashed_by_message_ids, #find_uids_by_message_ids, #initialize, #labels, #list_mailboxes, #list_mailboxes_with_attributes, #open_mailbox, #open_spam_mailbox, #open_trash_mailbox, #spam_mailbox, #trash, #trash_mailbox, #uids
Instance Method Details
#archive(uid) ⇒ Object
All emails in the thread must be archived in Gmail for the thread to get removed from the inbox
69
70
71
72
73
74
75
76
77
78
79
80
81
|
# File 'lib/imap/providers/gmail.rb', line 69
def archive(uid)
thread_id = thread_id_from_uid(uid)
emails_to_archive = emails_in_thread(thread_id)
emails_to_archive.each do |email|
labels = email["LABELS"]
new_labels = labels.reject { |l| l == "\\Inbox" }
store(email["UID"], "LABELS", labels, new_labels)
end
ImapSyncLog.log(
"Thread ID #{thread_id} (UID #{uid}) archived in Gmail mailbox for #{@username}",
:debug,
)
end
|
#emails(uids, fields, opts = {}) ⇒ Object
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
# File 'lib/imap/providers/gmail.rb', line 18
def emails(uids, fields, opts = {})
fields[fields.index("LABELS")] = X_GM_LABELS if fields.include?("LABELS")
emails = super(uids, fields, opts)
emails.each do |email|
email["LABELS"] = Array(email["LABELS"])
if email[X_GM_LABELS]
email["LABELS"] << Array(email.delete(X_GM_LABELS))
email["LABELS"].flatten!
end
email["LABELS"] << '\\Inbox' if @open_mailbox_name == "INBOX"
email["LABELS"].uniq!
end
emails
end
|
#emails_in_thread(thread_id) ⇒ Object
108
109
110
111
|
# File 'lib/imap/providers/gmail.rb', line 108
def emails_in_thread(thread_id)
uids_to_fetch = imap.uid_search("#{X_GM_THRID} #{thread_id}")
emails(uids_to_fetch, %w[UID LABELS])
end
|
#filter_mailboxes(mailboxes_with_attributes) ⇒ Object
Some mailboxes are just not useful or advisable to sync with. This is used for the dropdown in the UI where we allow the user to select the IMAP mailbox to sync with.
128
129
130
131
132
|
# File 'lib/imap/providers/gmail.rb', line 128
def filter_mailboxes(mailboxes_with_attributes)
mailboxes_with_attributes
.reject { |mb| (mb.attr & %i[Drafts Sent Junk Flagged Trash]).any? }
.map(&:name)
end
|
#imap ⇒ Object
14
15
16
|
# File 'lib/imap/providers/gmail.rb', line 14
def imap
@imap ||= super.tap { |imap| apply_gmail_patch(imap) }
end
|
#store(uid, attribute, old_set, new_set) ⇒ Object
40
41
42
43
|
# File 'lib/imap/providers/gmail.rb', line 40
def store(uid, attribute, old_set, new_set)
attribute = X_GM_LABELS if attribute == "LABELS"
super(uid, attribute, old_set, new_set)
end
|
#tag_to_flag(tag) ⇒ Object
54
55
56
57
58
|
# File 'lib/imap/providers/gmail.rb', line 54
def tag_to_flag(tag)
return :Flagged if tag == "starred"
super(tag)
end
|
#tag_to_label(tag) ⇒ Object
60
61
62
63
64
65
|
# File 'lib/imap/providers/gmail.rb', line 60
def tag_to_label(tag)
return '\\Important' if tag == "important"
return '\\Starred' if tag == "starred"
super(tag)
end
|
#thread_id_from_uid(uid) ⇒ Object
101
102
103
104
105
106
|
# File 'lib/imap/providers/gmail.rb', line 101
def thread_id_from_uid(uid)
fetched = imap.uid_fetch(uid, [X_GM_THRID])
raise "Thread not found for UID #{uid}!" if !fetched
fetched.last.attr[X_GM_THRID]
end
|
#to_tag(label) ⇒ Object
45
46
47
48
49
50
51
52
|
# File 'lib/imap/providers/gmail.rb', line 45
def to_tag(label)
return "starred" if label == :Flagged
return if label == "[Gmail]/All Mail"
label = label.to_s.gsub("[Gmail]/", "")
super(label)
end
|
#trash_move(uid) ⇒ Object
113
114
115
116
117
118
119
120
121
122
123
|
# File 'lib/imap/providers/gmail.rb', line 113
def trash_move(uid)
thread_id = thread_id_from_uid(uid)
email_uids_to_trash = emails_in_thread(thread_id).map { |e| e["UID"] }
imap.uid_move(email_uids_to_trash, trash_mailbox)
ImapSyncLog.log(
"Thread ID #{thread_id} (UID #{uid}) trashed in Gmail mailbox for #{@username}",
:debug,
)
{ trash_uid_validity: open_trash_mailbox, email_uids_to_trash: email_uids_to_trash }
end
|
#unarchive(uid) ⇒ Object
Though Gmail considers the email thread unarchived if the first email has the \Inbox label applied, we want to do this to all emails in the thread to be consistent with archive behaviour.
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
# File 'lib/imap/providers/gmail.rb', line 86
def unarchive(uid)
thread_id = thread_id_from_uid(uid)
emails_to_unarchive = emails_in_thread(thread_id)
emails_to_unarchive.each do |email|
labels = email["LABELS"]
new_labels = labels.dup
new_labels << "\\Inbox" if !new_labels.include?("\\Inbox")
store(email["UID"], "LABELS", labels, new_labels)
end
ImapSyncLog.log(
"Thread ID #{thread_id} (UID #{uid}) unarchived in Gmail mailbox for #{@username}",
:debug,
)
end
|