Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ tmtags

## PROJECT::GENERAL
*.pyc
build/
dist/
gmail.egg-info/

## PROJECT::SPECIFIC
*.rdb
Expand Down
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,16 @@ __This library is still under development, so please forgive some of the rough e

Heavily inspired by [Kriss "nu7hatch" Kowalik's GMail for Ruby library](https://github.com/nu7hatch/gmail)

## Author
## Contributors

* [Charlie Guo](https://github.com/charlierguo)
* [Charlie Guo](https://github.com/charlierguo) - Author of the original python2 package
* [Reuben Castelino](https://github.com/projectdelphai) - Edited by me to work with python3

## Installation

For now, installation is manual (`pip` support not yet implemented) and the only requirement is to use Python 2 (2.7+ to be precise):
For now, installation is manual (`pip` support not yet implemented) and the only requirement is to use Python 3

git clone git://github.com/charlierguo/gmail.git

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ReeeTaaa

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ReeeTaaa

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ReeeTaaa

git clone git://github.com/projectdelphai/gmail.git

## Features

Expand Down
14 changes: 7 additions & 7 deletions gmail/gmail.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import re
import imaplib

from mailbox import Mailbox
from utf import encode as encode_utf7, decode as decode_utf7
from exceptions import *
from .mailbox import Mailbox
from .utf import encode as encode_utf7, decode as decode_utf7
from .exceptions import *

class Gmail():
# GMail IMAP defaults
Expand Down Expand Up @@ -53,7 +53,7 @@ def fetch_mailboxes(self):
response, mailbox_list = self.imap.list()
if response == 'OK':
for mailbox in mailbox_list:
mailbox_name = mailbox.split('"/"')[-1].replace('"', '').strip()
mailbox_name = mailbox.decode().split('"/"')[-1].replace('"', '').strip()
mailbox = Mailbox(self)
mailbox.external_name = mailbox_name
self.mailboxes[mailbox_name] = mailbox
Expand Down Expand Up @@ -147,9 +147,9 @@ def copy(self, uid, to_mailbox, from_mailbox=None):
self.imap.uid('COPY', uid, to_mailbox)

def fetch_multiple_messages(self, messages):
fetch_str = ','.join(messages.keys())
fetch_str = ','.join(list(messages.keys()))
response, results = self.imap.uid('FETCH', fetch_str, '(BODY.PEEK[] FLAGS X-GM-THRID X-GM-MSGID X-GM-LABELS)')
for index in xrange(len(results) - 1):
for index in range(len(results) - 1):
raw_message = results[index]
if re.search(r'UID (\d+)', raw_message[0]):
uid = re.search(r'UID (\d+)', raw_message[0]).groups(1)[0]
Expand All @@ -159,7 +159,7 @@ def fetch_multiple_messages(self, messages):


def labels(self, require_unicode=False):
keys = self.mailboxes.keys()
keys = list(self.mailboxes.keys())
if require_unicode:
keys = [decode_utf7(key) for key in keys]
return keys
Expand Down
8 changes: 4 additions & 4 deletions gmail/mailbox.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from message import Message
from utf import encode as encode_utf7, decode as decode_utf7
from .message import Message
from .utf import encode as encode_utf7, decode as decode_utf7


class Mailbox():
Expand Down Expand Up @@ -60,7 +60,7 @@ def mail(self, prefetch=False, **kwargs):
# print search
response, data = self.gmail.imap.uid('SEARCH', *search)
if response == 'OK':
uids = filter(None, data[0].split(' ')) # filter out empty strings
uids = [_f for _f in data[0].decode().split(' ') if _f] # filter out empty strings

for uid in uids:
if not self.messages.get(uid):
Expand Down Expand Up @@ -91,7 +91,7 @@ def threads(self, prefetch=False, **kwargs):
if prefetch:
fetch_str = ','.join(uids)
response, results = self.gmail.imap.uid('FETCH', fetch_str, '(BODY.PEEK[] FLAGS X-GM-THRID X-GM-MSGID X-GM-LABELS)')
for index in xrange(len(results) - 1):
for index in range(len(results) - 1):
raw_message = results[index]
if re.search(r'UID (\d+)', raw_message[0]):
uid = re.search(r'UID (\d+)', raw_message[0]).groups(1)[0]
Expand Down
21 changes: 12 additions & 9 deletions gmail/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ def archive(self):

def parse_headers(self, message):
hdrs = {}
for hdr in message.keys():
for hdr in list(message.keys()):
hdrs[hdr] = message[hdr]
return hdrs

Expand All @@ -124,20 +124,23 @@ def parse_flags(self, headers):
def parse_labels(self, headers):
if re.search(r'X-GM-LABELS \(([^\)]+)\)', headers):
labels = re.search(r'X-GM-LABELS \(([^\)]+)\)', headers).groups(1)[0].split(' ')
return map(lambda l: l.replace('"', '').decode("string_escape"), labels)
return [l.replace('"', '').encode().decode("unicode_escape") for l in labels]
else:
return list()

def parse_subject(self, encoded_subject):
dh = decode_header(encoded_subject)
default_charset = 'ASCII'
return ''.join([ unicode(t[0], t[1] or default_charset) for t in dh ])

# dh is a list that has (str, None) and (bytes, encoding) objects
return ''.join(
value.decode(encoding) if encoding else value
for value, encoding in dh)

def parse(self, raw_message):
raw_headers = raw_message[0]
raw_headers = raw_message[0].decode()
raw_email = raw_message[1]

self.message = email.message_from_string(raw_email)
self.message = email.message_from_string(raw_email.decode())
self.headers = self.parse_headers(self.message)

self.to = self.message['to']
Expand All @@ -157,7 +160,7 @@ def parse(self, raw_message):

self.sent_at = datetime.datetime.fromtimestamp(time.mktime(email.utils.parsedate_tz(self.message['date'])[:9]))

self.flags = self.parse_flags(raw_headers)
self.flags = self.parse_flags(raw_headers.encode())

self.labels = self.parse_labels(raw_headers)

Expand All @@ -170,7 +173,7 @@ def parse(self, raw_message):
# Parse attachments into attachment objects array for this message
self.attachments = [
Attachment(attachment) for attachment in self.message._payload
if not isinstance(attachment, basestring) and attachment.get('Content-Disposition') is not None
if not isinstance(attachment, str) and attachment.get('Content-Disposition') is not None
]


Expand Down Expand Up @@ -210,7 +213,7 @@ def fetch_thread(self):
self.gmail.use_mailbox(original_mailbox.name)

# combine and sort sent and received messages
return sorted(dict(received_messages.items() + sent_messages.items()).values(), key=lambda m: m.sent_at)
return sorted(list(dict(list(received_messages.items()) + list(sent_messages.items())).values()), key=lambda m: m.sent_at)


class Attachment:
Expand Down
6 changes: 3 additions & 3 deletions gmail/utf.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

text_type = unicode
binary_type = str
text_type = str
binary_type = bytes

PRINTABLE = set(range(0x20, 0x26)) | set(range(0x27, 0x7f))

Expand Down Expand Up @@ -96,4 +96,4 @@ def modified_utf7(s):
def modified_deutf7(s):
s_utf7 = '+' + s.replace(',', '/') + '-'
# encode to latin-1: '+AP8-' => b'+AP8-', decode from utf-7 => '\xff'
return s_utf7.encode('latin-1').decode('utf-7')
return s_utf7.encode('latin-1').decode('utf-7')