-
-
Save BertrandBordage/e07e5fe8191590daafafe0dbb05b5a7b to your computer and use it in GitHub Desktop.
| """ | |
| Automatically replies to mails both unread and unanswered. | |
| WARNING: This answers to any both unread and unanswered mail, even if it is years old. | |
| Don’t use on a mailbox with old messages left unread and unanswered. | |
| Simply subclass ``AutoReplyer``, define the undefined class attribute, | |
| and call the ``run`` method on an instance. This loops until you stop the script | |
| (using Ctrl+C, typically) or until an error occurs, like a network failure. | |
| Example usage: | |
| from autoreplyer import AutoReplyer | |
| class YourAutoReplyer(AutoReplyer): | |
| imap_server = 'your.imap.server' | |
| imap_port = 1234 # Custom port, only use if the default one doesn’t work. | |
| imap_user = '[email protected]' | |
| imap_password = 'your_password' | |
| smtp_server = 'your.smtp.server' | |
| smtp_port = 5678 # Custom port, only use if the default one doesn’t work. | |
| smtp_user = '[email protected]' | |
| smtp_password = 'your_password' | |
| from_address = 'Your Displayed Name <[email protected]>' | |
| body = ''' | |
| Hello, | |
| I’m on vacation until a date I should mention here. | |
| You’ll have an answer when I’m back. | |
| Call Django in case of emergency. | |
| Have a nice day, | |
| You | |
| ''' | |
| body_html = ''' | |
| <p>Hello</p>, | |
| <p> | |
| I’m on vacation until a date I should mention here.<br /> | |
| You’ll have an answer when I’m back.<br /> | |
| Call <a href="tel:+1234567890">Django</a> in case of emergency. | |
| </p> | |
| <p> | |
| Have a nice day,<br /> | |
| You | |
| </p> | |
| ''' | |
| YourAutoReplyer().run() | |
| """ | |
| from email import message_from_bytes | |
| from email.mime.multipart import MIMEMultipart | |
| from email.mime.text import MIMEText | |
| from email.utils import make_msgid | |
| from imaplib import IMAP4, IMAP4_SSL, IMAP4_PORT, IMAP4_SSL_PORT | |
| from smtplib import SMTP, SMTP_SSL, SMTP_PORT, SMTP_SSL_PORT | |
| from subprocess import call | |
| from textwrap import dedent | |
| from time import sleep | |
| __author__ = 'Bertrand Bordage' | |
| __copyright__ = 'Copyright © 2016 Bertrand Bordage' | |
| __license__ = 'MIT' | |
| class AutoReplyer: | |
| refresh_delay = 5 # seconds | |
| imap_server = None | |
| imap_use_ssl = False | |
| imap_port = IMAP4_PORT | |
| imap_ssl_port = IMAP4_SSL_PORT | |
| imap_user = None | |
| imap_password = None | |
| smtp_server = None | |
| smtp_use_ssl = False | |
| smtp_port = SMTP_PORT | |
| smtp_ssl_port = SMTP_SSL_PORT | |
| smtp_user = None | |
| smtp_password = None | |
| from_address = None | |
| body = None | |
| body_html = None | |
| def __init__(self): | |
| if self.imap_use_ssl: | |
| self.imap = IMAP4_SSL(self.imap_server, self.imap_ssl_port) | |
| else: | |
| self.imap = IMAP4(self.imap_server, self.imap_port) | |
| self.imap.login(self.imap_user, self.imap_password) | |
| if self.smtp_use_ssl: | |
| self.smtp = SMTP_SSL(self.smtp_server, self.smtp_ssl_port) | |
| else: | |
| self.smtp = SMTP(self.smtp_server, self.smtp_port) | |
| self.smtp.login(self.smtp_user, self.smtp_password) | |
| def close(self): | |
| self.smtp.close() | |
| self.imap.logout() | |
| def create_auto_reply(self, original): | |
| mail = MIMEMultipart('alternative') | |
| mail['Message-ID'] = make_msgid() | |
| mail['References'] = mail['In-Reply-To'] = original['Message-ID'] | |
| mail['Subject'] = 'Re: ' + original['Subject'] | |
| mail['From'] = self.from_address | |
| mail['To'] = original['Reply-To'] or original['From'] | |
| mail.attach(MIMEText(dedent(self.body), 'plain')) | |
| mail.attach(MIMEText(self.body_html, 'html')) | |
| return mail | |
| def send_auto_reply(self, original): | |
| self.smtp.sendmail( | |
| self.from_address, [original['From']], | |
| self.create_auto_reply(original).as_bytes()) | |
| log = 'Replied to “%s” for the mail “%s”' % (original['From'], | |
| original['Subject']) | |
| print(log) | |
| try: | |
| call(['notify-send', log]) | |
| except FileNotFoundError: | |
| pass | |
| def reply(self, mail_number): | |
| self.imap.select(readonly=True) | |
| _, data = self.imap.fetch(mail_number, '(RFC822)') | |
| self.imap.close() | |
| self.send_auto_reply(message_from_bytes(data[0][1])) | |
| self.imap.select(readonly=False) | |
| self.imap.store(mail_number, '+FLAGS', '\\Answered') | |
| self.imap.close() | |
| def check_mails(self): | |
| self.imap.select(readonly=False) | |
| _, data = self.imap.search(None, '(UNSEEN UNANSWERED)') | |
| self.imap.close() | |
| for mail_number in data[0].split(): | |
| self.reply(mail_number) | |
| def run(self): | |
| try: | |
| while True: | |
| self.check_mails() | |
| sleep(self.refresh_delay) | |
| finally: | |
| self.close() |
Reply email can not add original message,How can I resolve it
Thanks a lot. Almost exactly what I was looking for
I have uploaded a modified version at: https://gist.github.com/praul/68710409583eb19c8c1b12c12a9302ff that has rebound protection.
It uses a simple sqlite database to prevent autoresponder-ping-pong and send only a reply every 12 hours by default.
... I further modded this and made it to an own repo and docker-image: https://github.com/praul/autoreply
Thank you for the base script.
hello man, first of all congrats for the work, the code is very clean.
please, how do I specify a subject to reply?
I want to reply only a specific subject not all the emails.
tks
@brcelso You can modify send_auto_reply and add a condition like if original['Subject'] not in {'First subject you want to reply to', 'Second subject you want to reply to'}: return. Of course, I recommend you to not stick to just a few precise subjects, as it will not catch Re:orFwd:emails. You should probably use a regular expression or a simplein` to check that an expression is contained in the subject of the original mail.
@satishrg007
I don't think autoreplyer is module. He gives us an example of how to use the file. The import is not from python libraries, but from the python file itself.