Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Best way to implement IMAP IDLE? #186

Open
TravisDart opened this issue May 10, 2018 · 5 comments
Open

Best way to implement IMAP IDLE? #186

TravisDart opened this issue May 10, 2018 · 5 comments

Comments

@TravisDart
Copy link

TravisDart commented May 10, 2018

I have an IMAP inbox and I want to listen for incoming mail. IMAP-wise, this can be done with the IDLE command. What would be the best way to implement this in Django Mailbox?

Currently, Django Mailbox uses imaplib, which doesn't natively support IDLE. One solution monkey patches imaplib. While monkey-patching is generally undesirable, the solution looks minimally invasive. (Note that I haven't delved into the implementation details of IDLE or tested this code.)

There's also an imaplib2 module (src) which supports IDLE, and replaces imaplib (with caveats). Yet changing modules seem more invasive that the monkey patch above.

As far as Django Mailbox goes, maybe a watch() method could be added to the ImapTransport class and run with a management command?

conn = mailbox.get_connection()
conn.watch()
@ad-m
Copy link
Collaborator

ad-m commented May 11, 2018

@TravisDart , are you sure imaplib2 support watch? See https://github.com/imaplib2/imaplib2/search?utf8=%E2%9C%93&q=watch&type= .

I think it's best to do it based on imaplib2. This requires the introduction of a pluggable transport backend mechanism. Now lists of backend are hard-coded (

def get_connection(self):
"""Returns the transport instance for this mailbox.
These will always be instances of
`django_mailbox.transports.base.EmailTransport`.
"""
if not self.uri:
return None
elif self.type == 'imap':
conn = ImapTransport(
self.location,
port=self.port if self.port else None,
ssl=self.use_ssl,
tls=self.use_tls,
archive=self.archive,
folder=self.folder
)
conn.connect(self.username, self.password)
elif self.type == 'gmail':
conn = GmailImapTransport(
self.location,
port=self.port if self.port else None,
ssl=True,
archive=self.archive
)
conn.connect(self.username, self.password)
elif self.type == 'pop3':
conn = Pop3Transport(
self.location,
port=self.port if self.port else None,
ssl=self.use_ssl
)
conn.connect(self.username, self.password)
elif self.type == 'maildir':
conn = MaildirTransport(self.location)
elif self.type == 'mbox':
conn = MboxTransport(self.location)
elif self.type == 'babyl':
conn = BabylTransport(self.location)
elif self.type == 'mh':
conn = MHTransport(self.location)
elif self.type == 'mmdf':
conn = MMDFTransport(self.location)
return conn
). Next to a new one back-end extend EmailTransport and can use watch.

I do not have free time to implement it, but I can assist.

@TravisDart
Copy link
Author

The watch() method would an addition to Django Mailbox and would fetch messages from imaplib2 and store the messages in Django.

So, rather than change the existing ImapTransport, we should create another transport (say, StreamingImapTransport) and integrate it into Django Mailbox through a new pluggable transport system? Not quite sure what you're envisioning with the pluggable transport system.

@ad-m
Copy link
Collaborator

ad-m commented May 12, 2018

I think that the selected code snippet requires rewriting so that it is possible to dynamically add pluggable forms of transport (protocol) and then add StreamingImapTransport outside the django-mailbox. Maybe replace line

to something like

transport_registry.get_for_type(self.type).from_uri(self.uri)

I also think that there should be a new transport instead of modifying the current one.

@TravisDart
Copy link
Author

It sound like it'd be best to make each 3rd-party transport a Django app. The transport could add itself to the transport registry in the app.py.

Honestly, it seems we're drifting off topic. I was wanting to implement IMAP IDLE, and I'm now implementing a pluggable transport system. I guess this is okay if it doesn't take us too far out of our way, but I was kind of thinking it'd just be a matter of hard-coding another transport like we already have.

@ad-m
Copy link
Collaborator

ad-m commented May 14, 2018

@TravisDart , I added some POC of pluggable transport registry: #188

I'd rather not add additional dependency to this library. Therefore, transports that use atypical libraries must be pluggable so that you can simply add custom transports with non-standard dependencies.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants