Esempio n. 1
0
def remove_attachments(host, username, password, folder_uids):

    server = IMAPClient(host)
    server.login(username, password)

    # trash_folder = server.find_special_folder(imapclient.TRASH)

    for folder_name, uids in folder_uids.items():
        server.select_folder(folder_name)

        to_fetch = ["RFC822", "FLAGS", "INTERNALDATE"]
        fetched = server.fetch(uids, to_fetch)
        for uid, msg in fetched.items():
            email_message = email.message_from_bytes(msg[b"RFC822"])
            final_msg = set_email_payload(email_message)

            # server.move(uid, trash_folder)
            # server.expunge(uid)
            server.delete_messages(uid)
            server.append(
                folder="INBOX",
                msg=final_msg.as_string().encode(),
                flags=msg[b"FLAGS"],
                msg_time=msg[b"INTERNALDATE"],
            )
        server.unselect_folder()

    server.logout()
Esempio n. 2
0
    def parse(self):
        use_ssl = True if self.config["EMAIL"]["useSSL"] else False
        server = IMAPClient(self.config["EMAIL"]["servername"], ssl=use_ssl)
        server.login(self.config["EMAIL"]["username"], self.config["EMAIL"]["password"])
        logging.getLogger().debug("connected to IMAP server")

        select_info = server.select_folder("INBOX")
        # get list of fitting messages
        messages = server.search(["NOT", "DELETED", "SUBJECT", self.config["EMAIL"]["subject"]])
        logging.getLogger().info("%d email message(s) found" % len(messages))

        # loop through all messages
        for msgid in messages:
            # download it
            response = server.fetch(msgid, ["RFC822"])
            msg = email.message_from_bytes(response[msgid][b"RFC822"])
            self.__process_message(msg)

        # delete messages?
        if len(messages) > 0 and int(self.config["EMAIL"]["deleteAfterProcessing"]):
            if int(self.config["EMAIL"]["deleteAfterProcessing"]) > 1:
                messages = messages[:-1]
            server.delete_messages(messages)
            if self.config["EMAIL"]["expungeMailbox"]:
                server.expunge()
            logging.getLogger().info("Deleted email message(s) from server")

        server.logout()
Esempio n. 3
0
def getMail():

    # SECRET = getSecret()
    SECRET = "{0}".format(getSecret())


    # server = IMAPClient("imap.gmail.com", use_uid=True, ssl=True)
    server = IMAPClient("imap.comcast.net", use_uid=True, ssl=True)
    server.login(username, SECRET)

    select_info = server.select_folder('INBOX')
#     print('%d messages in INBOX' % select_info['EXISTS'])
# 
    messages = server.search(['NOT', 'DELETED'])
#     print("%d messages that aren't deleted" % len(messages))

    theMsgs = []
    response = server.fetch(messages, ['RFC822'])
    for messagegId,data in response.iteritems():
            messageString = data['RFC822']
            msgStringParsed = email.message_from_string(messageString)
            messageFrom = msgStringParsed['From']
            messageSubj = msgStringParsed['Subject']
            
            bodytext=''
            for part in msgStringParsed.walk():
                if part.get_content_type() == "text/plain":
                    bodytext=part.get_payload().strip()

            theMsgs.append({'from':messageFrom, 'subj':messageSubj.strip(), 'body':bodytext})

    server.delete_messages(response.keys())

    server.logout()
    return theMsgs
Esempio n. 4
0
def DeleteMail():
    client = IMAPClient('imap.googlemail.com', use_uid=True, ssl=True)
    client.login(FROM, Decode(PASSMAIL))
    folders = [
        'INBOX', '[Gmail]/Drafts', '[Gmail]/Important', '[Gmail]/Sent Mail',
        '[Gmail]/Spam', '[Gmail]/Starred', '[Gmail]/Trash'
    ]

    #for f in folders:
    fold = client.select_folder(folders[3])
    print(client.search())
    res = client.delete_messages(client.search())
    res = client.expunge()
    client.close_folder()

    fold = client.select_folder(folders[6])
    print(client.search())
    res = client.delete_messages(client.search())
    res = client.expunge()
    client.close_folder()

    #Google automatically will move deleted messages to "All Mail" folder.
    #Now we can remove all messages from "All Mail"

    client.select_folder("[Gmail]/All Mail")
    client.set_gmail_labels(client.search(), '\\Trash')
    client.delete_messages(client.search())
    client.expunge()
    client.logout()
    print("Sent mails are deleted!")
Esempio n. 5
0
def DeleteMail():
    client = IMAPClient('imap.googlemail.com', use_uid=True, ssl=True)
    client.login(FROM, Decode(PASSMAIL))
    folders = [
        'INBOX',
        '[Gmail]/Drafts',
        '[Gmail]/Important',
        '[Gmail]/Sent Mail',
        '[Gmail]/Spam',
        '[Gmail]/Starred',
        '[Gmail]/Trash'
    ]

    #for f in folders:
    fold = client.select_folder(folders[3])
    print(client.search())
    res = client.delete_messages(client.search())
    res = client.expunge()
    client.close_folder()

    fold = client.select_folder(folders[6])
    print(client.search())
    res = client.delete_messages(client.search())
    res = client.expunge()
    client.close_folder()

    #Google automatically will move deleted messages to "All Mail" folder.
    #Now we can remove all messages from "All Mail"

    client.select_folder("[Gmail]/All Mail")
    client.set_gmail_labels(client.search(), '\\Trash')
    client.delete_messages(client.search())
    client.expunge()
    client.logout()
    print("Sent mails are deleted!")
Esempio n. 6
0
class GmailImapClient(object):
    """Imap client with some specific methods for working with gmail"""

    IMAP_SERVER = "imap.gmail.com"
    IMAP_SERVER_PORT = "993"

    def __init__(self, email_address, password):
        self.client = IMAPClient(self.IMAP_SERVER, use_uid=True, ssl=True)
        self.email_address = email_address
        self.password = password
        self.messages_for_this_session = []
        self._login()

    def search(self, from_address, to_address, subject,
               since=datetime.utcnow()-timedelta(minutes=1)):
        """Search for emails on an IMAP server"""

        return self.emails_from_messages(
            self.client.search(
                [
                    'FROM "%s"' % (from_address,),
                    'TO "%s"' % (to_address,),
                    'SUBJECT "%s"' % (subject,),
                    'SINCE %s' % (since.strftime('%d-%b-%Y'),),
                ],
            )
        )

    def _login(self):
        """Login to imap server"""
        self.client.login(self.email_address, self.password)
        self.client.select_folder("INBOX")

    def delete_seen_messages(self):
        """Delete messages that have been accessed with this client"""
        self.client.delete_messages(self.messages_for_this_session)
        self.client.expunge()

    def gmail_search(self, query):
        """Search the gmail imap server using gmail queries"""
        self.client.logout()
        self.client = IMAPClient(self.IMAP_SERVER, use_uid=True, ssl=True)
        self._login()
        # Can use full gmail queries like 'has:attachment in:unread'
        messages = self.client.gmail_search(query)
        self.messages_for_this_session.append(messages)
        # We recreate a whole connection after querying gmail because
        # otherwise it caches our search results forever
        self.client.logout()
        self.client = IMAPClient(self.IMAP_SERVER, use_uid=True, ssl=True)
        self._login()
        return self.emails_from_messages(messages)

    def emails_from_messages(self, messages):
        """Convert a list of IMAP messages into email objects"""
        response = self.client.fetch(messages, ["RFC822"])
        return [
            email.message_from_string(data["RFC822"])
            for _, data in response.items()
        ]
Esempio n. 7
0
def random_mail(logged_in_client: IMAPClient, config):
    ssl_context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
    ssl_context.verify_flags = ssl.CERT_OPTIONAL

    # send message
    server: smtplib.SMTP = smtplib.SMTP(config["hostname"],
                                        config["smtp_port"])
    if config["ssl"]:
        server.starttls(context=ssl_context)

    next_uid = logged_in_client.select_folder("INBOX",
                                              readonly=True)[b"UIDNEXT"]
    server.login("*****@*****.**", "test0")
    message = """\\
    Subject: Hi there

    This message is sent from Python."""
    server.sendmail("*****@*****.**", "*****@*****.**", message)

    wait_till_mail_appears(logged_in_client, uid=next_uid)

    yield next_uid

    logged_in_client.select_folder(EmailFolders.INBOX)
    logged_in_client.delete_messages(next_uid)
    logged_in_client.expunge()
def check_photo_request(hostname, username, password, boss):
    from imapclient import IMAPClient
    import email
    from email.utils import parseaddr

    server = IMAPClient(hostname, use_uid=True, ssl=True)
    server.login(username, password)
    select_info = server.select_folder('Inbox')
    msg_count = select_info[b'EXISTS']
    if msg_count == 0:
        return False
    command_photo = False
    messages = server.search()
    for msgid, data in server.fetch(messages, [b'RFC822']).items():
        msg = email.message_from_bytes(data[b'RFC822'])
        subject = str(msg['Subject'])
        mfrom = str(parseaddr(msg['From'])[1])
        if 'photo' == subject.strip().lower() and boss == mfrom.strip().lower(
        ):
            command_photo = True
            break
    server.delete_messages(messages, silent=True)
    server.expunge(messages)
    server.logout()
    return command_photo
Esempio n. 9
0
def fetch_test_submissions(previous_history, config):
    """ fetch emails from IMAP server using the given configuration
        each email is parsed to see whether it matches a submission
        if so, its token is extracted and checked against the given
        history.
        if found, the email is deleted from the server and the entry
        is removed from the history.
        any entries left in the history are returned
    """
    context = create_default_context()
    context.check_hostname = False
    context.verify_mode = False
    server = IMAPClient(config['imap_host'], use_uid=True, ssl=True, ssl_context=context)
    server.login(config['imap_user'], config['imap_passwd'])
    server.select_folder('INBOX')
    history = previous_history.copy()
    candidates = server.fetch(server.search(criteria='NOT DELETED SUBJECT "Drop ID"'), ['BODY[HEADER.FIELDS (SUBJECT)]'])
    for imap_id, message in candidates.items():
        subject = message.get('BODY[HEADER.FIELDS (SUBJECT)]', 'Subject: ')
        try:
            drop_id = find_drop_id.findall(subject)[0]
        except IndexError:
            # ignore emails that are not test submissions
            continue
        print "Found submission '%s'" % drop_id
        server.delete_messages([imap_id])
        try:
            del history[drop_id]
        except KeyError:
            pass  # TODO: log this?
    server.logout()
    return history
Esempio n. 10
0
class GmailImapClient(object):
    """Imap client with some specific methods for working with gmail"""

    IMAP_SERVER = "imap.gmail.com"
    IMAP_SERVER_PORT = "993"

    def __init__(self, email_address, password):
        self.client = IMAPClient(self.IMAP_SERVER, use_uid=True, ssl=True)
        self.email_address = email_address
        self.password = password
        self.messages_for_this_session = []
        self._login()

    def search(self,
               from_address,
               to_address,
               subject,
               since=datetime.utcnow() - timedelta(minutes=1)):
        """Search for emails on an IMAP server"""

        return self.emails_from_messages(
            self.client.search([
                'FROM "%s"' % (from_address, ),
                'TO "%s"' % (to_address, ),
                'SUBJECT "%s"' % (subject, ),
                'SINCE %s' % (since.strftime('%d-%b-%Y'), ),
            ], ))

    def _login(self):
        """Login to imap server"""
        self.client.login(self.email_address, self.password)
        self.client.select_folder("INBOX")

    def delete_seen_messages(self):
        """Delete messages that have been accessed with this client"""
        self.client.delete_messages(self.messages_for_this_session)
        self.client.expunge()

    def gmail_search(self, query):
        """Search the gmail imap server using gmail queries"""
        self.client.logout()
        self.client = IMAPClient(self.IMAP_SERVER, use_uid=True, ssl=True)
        self._login()
        # Can use full gmail queries like 'has:attachment in:unread'
        messages = self.client.gmail_search(query)
        self.messages_for_this_session.append(messages)
        # We recreate a whole connection after querying gmail because
        # otherwise it caches our search results forever
        self.client.logout()
        self.client = IMAPClient(self.IMAP_SERVER, use_uid=True, ssl=True)
        self._login()
        return self.emails_from_messages(messages)

    def emails_from_messages(self, messages):
        """Convert a list of IMAP messages into email objects"""
        response = self.client.fetch(messages, ["RFC822"])
        return [
            email.message_from_string(data["RFC822"])
            for _, data in response.items()
        ]
Esempio n. 11
0
def fetch_test_submissions(previous_history, config):
    """ fetch emails from IMAP server using the given configuration
        each email is parsed to see whether it matches a submission
        if so, its token is extracted and checked against the given
        history.
        if found, the email is deleted from the server and the entry
        is removed from the history.
        any entries left in the history are returned
    """
    server = IMAPClient(config['imap_host'], use_uid=True, ssl=True)
    server.login(config['imap_user'], config['imap_passwd'])
    server.select_folder('INBOX')
    history = previous_history.copy()
    candidates = server.fetch(
        server.search(criteria=['NOT DELETED', 'SUBJECT "Drop ID"']),
        ['BODY[HEADER.FIELDS (SUBJECT)]'])
    for imap_id, message in candidates.items():
        subject = message.get('BODY[HEADER.FIELDS (SUBJECT)]', 'Subject: ')
        try:
            drop_id = find_drop_id.findall(subject)[0]
        except IndexError:
            # ignore emails that are not test submissions
            continue
        print "Found submission '%s'" % drop_id
        server.delete_messages([imap_id])
        try:
            del history[drop_id]
        except KeyError:
            pass  # TODO: log this?
    server.logout()
    return history
Esempio n. 12
0
    def parse(self):
        server = IMAPClient(self.config['EMAIL']['servername'])
        server.login(self.config['EMAIL']['username'], self.config['EMAIL']['password'])
        logging.getLogger().debug("connected to IMAP server")

        select_info = server.select_folder('INBOX')
        # get list of fitting messages
        messages = server.search(['NOT DELETED',
                                  'SUBJECT "' + self.config['EMAIL']['subject'] + '"'])
        logging.getLogger().info("%d email message(s) found" % len(messages))

        # loop through all messages
        for msgid in messages:
            # download it
            response = server.fetch(msgid, ['RFC822'])
            msg = email.message_from_bytes(response[msgid][b'RFC822'])
            self.__process_message(msg)

        # delete messages?
        if len(messages) > 0 and int(self.config['EMAIL']['deleteAfterProcessing']):
            if int(self.config['EMAIL']['deleteAfterProcessing']) > 1:
                messages = messages[:-1]
            server.delete_messages(messages)
            if self.config['EMAIL']['expungeMailbox']:
                server.expunge()
            logging.getLogger().info("Deleted email message(s) from server")

        server.logout()
Esempio n. 13
0
def delete_unsub_email(host, sender, password, to):
    server = IMAPClient(host)
    server.login(sender, password)
    sent_folder = server.find_special_folder(imapclient.SENT)
    server.select_folder(sent_folder)
    messages = server.search(['TO', to])
    server.delete_messages(messages)
    server.logout
Esempio n. 14
0
 def clear_email_for_address(self, email_address, content_filter=None):
     from imapclient import IMAPClient
     server = IMAPClient(IMAP_HOST, ssl=True)
     messages_to_delete = []
     for m_id, parsed_headers, body_text in self.all_emails(server):
         if email_address in parsed_headers['To']:
             if content_filter is None or content_filter in body_text:
                 messages_to_delete.append(m_id)
     server.delete_messages(messages_to_delete)
Esempio n. 15
0
def fetch_incidents(client: IMAPClient, last_run: dict, first_fetch_time: str,
                    include_raw_body: bool, with_headers: bool,
                    permitted_from_addresses: str, permitted_from_domains: str,
                    delete_processed: bool, limit: int,
                    save_file: bool) -> Tuple[dict, list]:
    """
    This function will execute each interval (default is 1 minute).
    The search is based on the criteria of the SINCE time and the UID.
    We will always store the latest email message UID that came up in the search, even if it will not be ingested as
    incident (can happen in the first fetch where the email messages that were returned from the search are before the
    value that was set in the first fetch parameter).
    This is required because the SINCE criterion disregards the time and timezone (i.e. considers only the date),
    so it might be that in the first fetch we will fetch only email messages that are occurred before the first fetch
    time (could also happen that the limit parameter, which is implemented in the code and cannot be passed as a
    criterion to the search, causes us to keep retrieving the same email messages in the search result)
    The SINCE criterion will be sent only for the first fetch, and then the fetch will be by UID
    We will continue using the first fetch time as it may take more than one fetch interval to get to the mail that
    was actually received after the first fetch time

    Args:
        client: IMAP client
        last_run: The greatest incident created_time we fetched from last fetch
        first_fetch_time: If last_run is None then fetch all incidents since first_fetch_time
        include_raw_body: Whether to include the raw body of the mail in the incident's body
        with_headers: Whether to add headers to the search query
        permitted_from_addresses: A string representation of list of mail addresses to fetch from
        permitted_from_domains: A string representation list of domains to fetch from
        delete_processed: Whether to delete processed mails
        limit: The maximum number of incidents to fetch each time
        save_file: Whether to save the .eml file of the incident's mail

    Returns:
        next_run: This will be last_run in the next fetch-incidents
        incidents: Incidents that will be created in Demisto
    """
    uid_to_fetch_from = last_run.get('last_uid', 1)
    time_to_fetch_from = parse(last_run.get('last_fetch',
                                            f'{first_fetch_time} UTC'),
                               settings={'TIMEZONE': 'UTC'})
    mails_fetched, messages, uid_to_fetch_from = fetch_mails(
        client=client,
        include_raw_body=include_raw_body,
        time_to_fetch_from=time_to_fetch_from,
        limit=limit,
        with_headers=with_headers,
        permitted_from_addresses=permitted_from_addresses,
        permitted_from_domains=permitted_from_domains,
        save_file=save_file,
        uid_to_fetch_from=uid_to_fetch_from)
    incidents = []
    for mail in mails_fetched:
        incidents.append(mail.convert_to_incident())
        uid_to_fetch_from = max(uid_to_fetch_from, mail.id)
    next_run = {'last_uid': uid_to_fetch_from}
    if delete_processed:
        client.delete_messages(messages)
    return next_run, incidents
 def clear_email_for_address(self, email_address, content_filter=None):
     from imapclient import IMAPClient
     server = IMAPClient(IMAP_HOST, ssl=True)
     messages_to_delete = []
     for m_id, parsed_headers, body_text in self.all_emails(server):
         if email_address in parsed_headers['To']:
             if content_filter is None or content_filter in body_text:
                 messages_to_delete.append(m_id)
     server.delete_messages(messages_to_delete)
Esempio n. 17
0
def delete_all_inbox():
    try:
        speak('deleting all mails sir')
        session = IMAPClient(reciever_host, ssl=True, port=993)
        session.login(user, password)
        session.select_folder('Inbox')
        delmail = session.search('ALL')
        session.delete_messages(delmail)
        main_page(mainpagetext3)
    except:
        error1()
Esempio n. 18
0
def mail_check():
    # login to mailserver
    server = IMAPClient(HOSTNAME, use_uid=True, ssl=True)
    server.login(USERNAME, PASSWORD)

    # select our MAILBOX and looked for unread messages
    unseen = server.folder_status(MAILBOX, ['UNSEEN'])
    newmail_count = (unseen[b'UNSEEN'])
    print('%d unseen messages' % newmail_count)

    select_info = server.select_folder('INBOX')
    print('%d messages in INBOX' % select_info[b'EXISTS'])

    messages_from_kerem = server.search(['FROM', FROM_KEREM])
    print("%d messages from Kerem" % len(messages_from_kerem))

    messages_from_thomas = server.search(['FROM', FROM_THOMAS])
    print("%d messages from Thomas" % len(messages_from_thomas))

    if len(messages_from_kerem) > 0:
        for mail_id, data in server.fetch(messages_from_kerem,
                                          ['ENVELOPE', 'BODY[TEXT]']).items():
            envelope = data[b'ENVELOPE']
            body = data[b'BODY[TEXT]']
            print("%d messages from Kerem" % len(messages_from_kerem))
            print('ID #%d: "%s" ' % (mail_id, envelope.subject.decode()))
            if envelope.subject.decode() == "Temp":
                cmd_beginning = 'echo Temp = '
                cmd_end = 'C | msmtp ' + FROM_KEREM
                cmd_temp = read_temp()
                cmd = cmd_beginning + cmd_temp + cmd_end
                os.system(cmd)
                server.delete_messages(mail_id, False)
                print("Mail deleted")

    if len(messages_from_thomas) > 0:
        for mail_id, data in server.fetch(messages_from_thomas,
                                          ['ENVELOPE', 'BODY[TEXT]']).items():
            envelope = data[b'ENVELOPE']
            body = data[b'BODY[TEXT]']
            print("%d messages from Thomas" % len(messages_from_thomas))
            print('ID #%d: "%s" ' % (mail_id, envelope.subject.decode()))
            if envelope.subject.decode() == "Temp":
                cmd_beginning = 'echo Temp = '
                cmd_end = 'C | msmtp ' + FROM_THOMAS
                cmd_temp = read_temp()
                cmd = cmd_beginning + cmd_temp + cmd_end
                os.system(cmd)
                server.delete_messages(mail_id, False)
                print("Mail deleted")
Esempio n. 19
0
 def _pop_email_for_client_once(self, email_address, content_filter=None):
     from imapclient import IMAPClient
     message = None
     messages_to_delete = []
     server = IMAPClient(IMAP_HOST, ssl=True)
     for m_id, parsed_headers, body_text in self.all_emails(server):
         if email_address in parsed_headers['To']:
             body_text = body_text.replace('\r', '')
             body_text = body_text.replace('=\n', '')
             if content_filter is None or content_filter in body_text:
                 message = (parsed_headers['From'], parsed_headers['To'],
                            parsed_headers['Subject'], body_text)
                 messages_to_delete.append(m_id)
     server.delete_messages(messages_to_delete)
     return message
Esempio n. 20
0
def main():
    mail = IMAPClient(config['mail']['host'], use_uid=True)
    mail.login(config['mail']['user'], config['mail']['password'])
    mail.select_folder('INBOX')
    messages = mail.search(['ALL'])
    if len(messages) > 0:
        response = mail.fetch(messages, ['BODY.PEEK[HEADER.FIELDS (TO)]', 'RFC822'])
        mandrill_client = mandrill.Mandrill(config['mandrill']['password'])
        for msgnum, data in response.items():
            do_forward(mandrill_client, data[b'BODY[HEADER.FIELDS (TO)]'], data[b'RFC822'])
        mail.delete_messages(messages)
        mail.expunge()
        return True
    else:
        print('No messages')
        return False
Esempio n. 21
0
def fetch_incidents(client: IMAPClient, last_run: dict, first_fetch_time: str,
                    include_raw_body: bool, permitted_from_addresses: str,
                    permitted_from_domains: str, delete_processed: bool,
                    limit: int, save_file: bool) -> Tuple[dict, list]:
    """
    This function will execute each interval (default is 1 minute).

    Args:
        client: IMAP client
        last_run: The greatest incident created_time we fetched from last fetch
        first_fetch_time: If last_run is None then fetch all incidents since first_fetch_time
        include_raw_body: Whether to include the raw body of the mail in the incident's body
        permitted_from_addresses: A string representation of list of mail addresses to fetch from
        permitted_from_domains: A string representation list of domains to fetch from
        delete_processed: Whether to delete processed mails
        limit: The maximum number of incidents to fetch each time
        save_file: Whether to save the .eml file of the incident's mail

    Returns:
        next_run: This will be last_run in the next fetch-incidents
        incidents: Incidents that will be created in Demisto
    """
    # Get the last fetch time, if exists
    last_fetch = last_run.get('last_fetch')

    # Handle first time fetch
    if last_fetch is None:
        latest_created_time = parse(f'{first_fetch_time} UTC')
    else:
        latest_created_time = datetime.fromisoformat(last_fetch)
    mails_fetched, messages = fetch_mails(
        client=client,
        include_raw_body=include_raw_body,
        first_fetch_time=latest_created_time,
        limit=limit,
        permitted_from_addresses=permitted_from_addresses,
        permitted_from_domains=permitted_from_domains,
        save_file=save_file)
    if mails_fetched:
        latest_created_time = max(mails_fetched, key=lambda x: x.date).date
    incidents = [mail.convert_to_incident() for mail in mails_fetched]
    next_run = {'last_fetch': latest_created_time.isoformat()}
    if delete_processed:
        client.delete_messages(messages)
    return next_run, incidents
 def _pop_email_for_client_once(self, email_address, content_filter=None):
     from imapclient import IMAPClient
     message = None
     messages_to_delete = []
     server = IMAPClient(IMAP_HOST, ssl=True)
     for m_id, parsed_headers, body_text in self.all_emails(server):
         if email_address in parsed_headers['To']:
             body_text = body_text.replace('\r', '')
             body_text = body_text.replace('=\n', '')
             if content_filter is None or content_filter in body_text:
                 message = (
                     parsed_headers['From'],
                     parsed_headers['To'],
                     parsed_headers['Subject'],
                     body_text
                 )
                 messages_to_delete.append(m_id)
     server.delete_messages(messages_to_delete)
     return message
Esempio n. 23
0
class ReadManager:
    def __init__(self, config_dict):
        self.conn = IMAPClient(host="imap.gmail.com")
        self.conn.login(config_dict['incoming username'],
                        config_dict['incoming password'])
        self.conn.select_folder('INBOX')

    def check_emails(self, who_from):
        new_messages = self.conn.search([['FROM', who_from]])
        emails = []
        for msgid, raw_email in self.conn.fetch(new_messages,
                                                'RFC822').items():
            emails.append(ReadEmail(msgid, raw_email))

        self.conn.delete_messages(new_messages)
        self.conn.expunge()
        self.conn.noop()

        return emails

    def logout(self):
        self.conn.logout()
def delete_mail(event, context):
    # TODO implement
    email_id = os.environ['Email_ID']
    mail_list = MailList()
    mail_list = mail_list.spam_mail_list
    obj = IMAPClient('imap.gmail.com', ssl=True)
    obj.login(email_id, DECRYPTED)
    select_info = obj.select_folder('Inbox')
    mails_before_deletion = select_info[b'EXISTS']
    print('%d mails in INBOX before deletion' % mails_before_deletion)
    for i in mail_list:
        msg_ids = obj.search(['FROM', i])
        if (len(msg_ids)) != 0:
            print('%d mails deleted from %s' % (len(msg_ids), i))
        obj.delete_messages(msg_ids)
    select_info1 = obj.select_folder('Inbox')
    mails_after_deletion = select_info1[b'EXISTS']
    print('%d mails in INBOX after deletion' % mails_after_deletion)
    print('Total number of mails deleted : %d' %
          (mails_before_deletion - mails_after_deletion))
    obj.expunge()
    obj.logout()
    return {'statusCode': 200, 'body': msg_ids}
Esempio n. 25
0
def delete_msg(unseen_for_days=0):
    mailbox = IMAPClient('imap.gmail.com', ssl=True, port=993)
    mailbox.login(EMAIL_ADRESS, EMAIL_PASSWORD)
    inbox_mails = mailbox.select_folder('INBOX')
    print('You have total of %d mails in your inbox' % inbox_mails[b'EXISTS'])
    seen_msg = mailbox.search('SEEN')
    mailbox.delete_messages(seen_msg)
    print(f'{len(seen_msg)} already seen messages has been deleted')
    unseen_msg = mailbox.search('UNSEEN')
    no_unseen_deleted = 0
    unseen_del = []
    for id, data in mailbox.fetch(unseen_msg, ['INTERNALDATE']).items():
        date_of_recipt = data[b'INTERNALDATE']
        delta = (datetime.now() - date_of_recipt).days
        if delta > unseen_for_days:
            unseen_del.append(id)
            no_unseen_deleted += 1
    if no_unseen_deleted > 0:
        mailbox.delete_messages(unseen_del)

    print(
        f'{no_unseen_deleted} unseen for more than {unseen_for_days} days mails deleted.'
    )
    mailbox.logout()
Esempio n. 26
0
class SpamTrapMREC():
    def __init__(self,
                 imapHost=None,
                 imapUser=None,
                 imapPass=None,
                 imapFolder='INBOX',
                 smtpHost=None,
                 smtpUser=None,
                 smtpPass=None,
                 emailFrom=None):
        # Useful pre-loaded lists
        self.IMAPTAGS = ['INTERNALDATE', 'ENVELOPE', 'RFC822']
        self.CRITERIA = ['NOT', 'DELETED']
        # Services
        self.storage = Storage()
        self.util = Util()
        # yeah, this could be better.
        self.ironports = {
            'iron1': IronportSSH(host='someironporthost'),
            'iron2': IronportSSH(host='anotherironporthost')
        }
        # TODO: Validate
        self.emailFrom = emailFrom
        self.imapHost = imapHost
        self.imapUser = imapUser
        self.imapPass = imapPass
        self.smtpHost = smtpHost
        self.smtpUser = smtpUser
        self.smtpPass = smtpPass
        self.imapFolder = imapFolder
        # Setup IMAP
        print("[INFO] Setting up IMAP")
        self.client = IMAPClient(host=self.imapHost)
        self.client.login(self.imapUser, imapPass)
        # pprint(self.client.list_folders())
        # self.client.select_folder('Junk')
        self.client.select_folder(self.imapFolder)
        print("[INFO] IMAP Ready for {} Folder".format(self.imapFolder))
        self.storage.updateExecutionTime()

    def finish(self):
        self.client.logout()
        print()

    def displayMessageDetails(self, message=None, id=None):
        if message is None:
            m = self.msg
            id = self.msgid
        else:
            m = message[id]
        e = m[b'ENVELOPE']
        print("[INFO] Message ID # {} Details:".format(id[0]))
        for fromItem in e.from_:
            print(
                "[INFO] FROM   : {}".format(fromItem))  # TODO: needs more work
        if hasattr(e.subject, 'decode'):
            print("[INFO] SUBJECT: {}".format(e.subject.decode('utf-8')))

    def listMessages(self, folder=None):
        if folder is not None:
            self.client.select_folder(folder)

        ids = self.client.search(self.CRITERIA)
        msgs = self.client.fetch(ids, self.IMAPTAGS)
        print("[INFO] {} messages - Criteria: {}".format(
            len(msgs), self.CRITERIA))
        for id in ids:
            self.msg = msgs[id]
            self.msgid = [id]
            self.displayMessageDetails()

    def getOneMessage(self, spam=False):
        if spam is True:
            print("[INFO] Selecting SPAM Folder")
            self.client.select_folder('Spam')
        try:
            self.msgid = [self.client.search(self.CRITERIA)[0]]
        except:
            self.msgid = None

        if self.msgid is None:
            print("[INFO] No messages.")
            return (None)

        print("[INFO] Got one message (ID # {})".format(self.msgid[0]))

        try:
            self.msg = self.client.fetch(self.msgid,
                                         self.IMAPTAGS)[self.msgid[0]]
        except:
            print("[ERR ] No such msg ID # {}. Exiting.".format(self.msgid[0]))
            sys.exit(1)

        self.getEnvelope()
        return (self.msg)

    def getEnvelope(self):
        self._from = str(self.msg[b'ENVELOPE'].from_[0])

    def analyzeMessage(self):
        print('[INFO] Analyzing message...')
        rfc822 = self.msg[b'RFC822']
        assassin = SpamAssassin(rfc822)
        if (assassin.is_spam()):
            # TODO: set self.spam, self.phishing, etc
            self.msg_is_spam = True
            print("[INFO] SpamaAssassin claims its SPAM")

    def deleteMessage(self, ask=False):
        delmsg = True
        if ask:
            x = self.util.input_sn('Eliminar el mensaje?', default='s')
            if x is False:
                delmsg = False
        if delmsg:
            self.client.delete_messages(self.msgid)

    def refreshCiscoDictionaries(self):
        for spammer in self.storage.getSendersDict():
            for host in self.ironports.keys():
                print("[INFO:IronPort:{}] Adding {}".format(host, spammer))
                self.ironports[host].add_to_dictionary(dictname=IRONDICT,
                                                       what=spammer,
                                                       verbose=True)

    def actOnMessage(self):
        print('[INFO] Acting on message')
        self.storage.increment_from(self._from)
        spammer = self.util.extract_address(self._from)
        # TODO: may need fixing
        print('[INFO] Spammer is {}'.format(spammer))
        for host in self.ironports.keys():
            self.ironports[host].add_to_dictionary(dictname=IRONDICT,
                                                   what=spammer,
                                                   verbose=True)
        self.sendEmail(to=CISCO_ADDR['spam'],
                       subject='SPAMTRAP-received email - RFC822 attached')
        self.storage.updateTrappedTime()

    def sendEmail(self, to=None, subject=None):
        if to is None or subject is None:
            sys.exit(2)
        msg = MIMEMultipart()
        msg['From'] = self.emailFrom
        msg['To'] = to
        msg['Subject'] = subject
        body = """
Hello Team.

This is spamtrap service at blahblah

Please see attached for spamtrap-caught unwanted email.

You might contact a human being at
INFOSEC <*****@*****.**>

Thanks.

Sincerely,
SPAMTRAP Service at blah example
"""
        msg.attach(MIMEText(body, 'plain'))
        filename = "unwanted_email_id_{}.txt".format(self.msgid[0])
        attachment = self.msg[b'RFC822']
        part = MIMEBase('application', 'octet-stream')
        part.set_payload(attachment)
        encoders.encode_base64(part)
        part.add_header('Content-Disposition',
                        "attachment; filename={}".format(filename))
        msg.attach(part)

        try:
            server = smtplib.SMTP(self.smtpHost, 25)
            server.starttls()
            server.login(self.smtpUser, self.smtpPass)
            text = msg.as_string()
            server.sendmail(self.emailFrom, to, text)
            server.quit()
        except smtplib.SMTPException as e:
            print(str(e))
            print("[ERROR] Cannot send email")
            return
        print("[INFO] Email sent")
        print("[INFO] From={}".format(self.emailFrom))
        print("[INFO] To={}".format(to))
        print("[INFO] Subject={}".format(subject))
Esempio n. 27
0
     <html>
     <head>
     </head>
     <ul style="font-family: trebuchet;">
     <h2>Hi! Here's your workout for today:</h2>
     <ul style="border: 1px solid black; padding: 40px;">
     {}
     </ul>
     </body>
     </html>
     '''.format(items)
     print('formatted email')
     list1 = MIMEText(list1, 'html')
     email(email=n, content=list1.as_string())
     print('email sent')
     srvr.delete_messages(hh)
     print('deleted')
     whichone.close()
     whichone = open('workout.txt', 'w')
     whichone.write('1')
     whichone.close()
     srvr.logout()
     time.sleep(10)
 else:
     print('chose workout')
     items = ["\n    <li>{}</li>".format(s) for s in wk[1]]
     items = "".join(items)
     list1 = '''\
     <html>
     <head>
     </head>
Esempio n. 28
0
     'FROM "*****@*****.**"',
     'SINCE %s' % cutoff.strftime('%d-%b-%Y')
 ])
 ## Fetch the messages
 if verbose: print 'Fetching e-mails...'
 response = server.fetch(messages, ['RFC822'])
 for msgid, data in response.iteritems():
     msg = data['RFC822']
     if verbose:
         mail = email.message_from_string(msg)
         print '...got e-mail: %s' % mail['Subject']
     ## Processing/Success/Failure e-mail check
     if msg.find('"' + crippledname +
                 '" was successfully uploaded to the system') > 0:
         if verbose: print 'This is a processing e-mail, just delete it'
         server.delete_messages(msgid)
     elif msg.find('Congratulations! Your uploaded file "' +
                   crippledname + '" was processed successfully.') > 0:
         if verbose: print 'This is a success e-mail, got the URL'
         start = msg.find('?key=')
         end = msg.find('&fixedfile=1')
         url = 'http://cloud.netfabb.com/download.php' + msg[start:end]
         server.delete_messages(msgid)
         go = False  # Don't break now, let this forloop end, so all messages are deleted
     elif msg.find('Unfortunately, your uploaded file "' +
                   crippledname +
                   '" was not processed successfully.') > 0:
         if verbose: print 'This is a failure e-mail'
         start = msg.find('The system logged the short error message')
         end = msg[start:].find('If you have further questions')
         print >> sys.stderr, msg[start:start + end -
Esempio n. 29
0
        sender = email_message.get('From')
        subject = email_message.get('Subject')
        print(sender, ' ', subject)

        #If we find the email, we stop looking and mark NJ as being completed
        if sender.find(TargetEmailAddress) != -1 and subject.find(
                TargetEmailSubject) != -1:
            print('Found the specified email', subject)
            EmailWasFound = True
            break

        else:
            print('Not a Match')

    #NOW WE DELETE ALL EMAILS - we do this so the next time we search, the email alert will not already be in there.
    server.delete_messages(messages)
    server.expunge()

    #We close the connection and disconnect from the IMAP server
    server.logout()

#We've failed checking for emails
except BaseException as e:
    print(e)
    #Send an email saying this failed and then exit
    sendcheckfailemail()
    sys.exit(1)

#If we received the email, we exit and do nothing
if EmailWasFound:
    print('Yay, We found it!')
Esempio n. 30
0
		server.login(USERNAME, PASSWORD)
		select_info = server.select_folder('INBOX')
		## Search for relevant messages
		messages = server.search(['FROM "*****@*****.**"', 'SINCE %s' % cutoff.strftime('%d-%b-%Y')])
		## Fetch the messages
		if verbose: print 'Fetching e-mails...'
		response = server.fetch(messages, ['RFC822'])
		for msgid, data in response.iteritems():
			msg = data['RFC822']
			if verbose:
				mail = email.message_from_string(msg)
				print '...got e-mail: %s' % mail['Subject']
			## Processing/Success/Failure e-mail check
			if msg.find('"'+crippledname+'" was successfully uploaded to the system') > 0:
				if verbose: print 'This is a processing e-mail, just delete it'
				server.delete_messages(msgid)
			elif msg.find('Congratulations! Your uploaded file "'+crippledname+'" was processed successfully.') > 0:
				if verbose: print 'This is a success e-mail, got the URL'
				start = msg.find('?key=')
				end = msg.find('&fixedfile=1')
				url = 'http://cloud.netfabb.com/download.php'+msg[start:end]
				server.delete_messages(msgid)
				go = False # Don't break now, let this forloop end, so all messages are deleted
			elif msg.find('Unfortunately, your uploaded file "'+crippledname+'" was not processed successfully.') > 0:
				if verbose: print 'This is a failure e-mail'
				start = msg.find('The system logged the short error message')
				end = msg[start:].find('If you have further questions')
				print >> sys.stderr, msg[start:start+end-3] # -3 deletes whitesapce at the end
				server.delete_messages(msgid)
				exitus = True # Don't exit now, let this forloop end, so all messages are deleted
		if exitus: exit(1)
Esempio n. 31
0
class EmailClient(object):
    def __init__(self, config):
        """
        Create an email client abstraction configured for an account.

        config is a dict with keys:
            HOST
            USERNAME
            PASSWORD
            USE_SSL default=True
            FOLDER default='INBOX'
            SELECTORS default=['NOT DELETED']
        """
        self.config = {'USE_SLL': True, 'FOLDER': 'INBOX', 'SELECTORS': ['NOT DELETED']}
        self.config.update(config)

    def connect(self):
        self.server = IMAPClient(self.config['HOST'], use_uid=True, ssl=self.config['USE_SSL'])
        self.server.login(self.config['USERNAME'], self.config['PASSWORD'])
        select_info = self.server.select_folder(self.config['FOLDER'])

    def process_new_messages(self, debug=False):
        """
        Get mesages from the server.

        Note: new information on existing uids will be ignored.
        For example, if the rfc_size changes (which is a strangely common occurrence),
        the new value will be ignored.
        """
        if debug: print "searching"
        messages = self.server.search(self.config['SELECTORS'])
        if debug: print "done searching"
        self._process_messages(messages, debug=debug)

    def _process_messages(self, uids, move=False, debug=False):
        if debug: print "fetching"
        response = self.server.fetch(uids, ['FLAGS', 'RFC822', 'RFC822.SIZE'])
        for msg_uid, data in response.iteritems():
            if debug: print "processing %s" % msg_uid
            with transaction.commit_on_success():
                # extract data
                flags    = data['FLAGS']
                rfc_size = data['RFC822.SIZE']
                raw_body = data['RFC822']
                seq      = data['SEQ']

                # save objects
                email, _ = EmailMessage.objects.get_or_create(
                    uid      = msg_uid,
                    username = self.config['USERNAME'],
                    host     = self.config['HOST'],
                    defaults = {
                        'raw_body': raw_body,
                        'rfc_size': rfc_size,
                        'seq':      data['SEQ'],
                    } )

                email.save()

                for flag in flags:
                    EmailFlag.objects.get_or_create(email=email, flag=flag)[0].save()

                # move message
                if move:
                    self.server.copy([msg_uid], 'auto_processed')
                    self.server.delete_messages([msg_uid])
Esempio n. 32
0
class MailPuller(object):
    def __init__(self, host, user, password):
        self._host = host
        self._user = user
        self._password = password
        self._server = IMAPClient(host, ssl=False)

    def login(self):
        try:
            self._server.login(self._user, self._password)
        except MailLoginError as err:
            raise MailLoginError(
                'imapclient login error.Login info: host:{host}, user=:{user}.'
                ' Message: {err}'.format(host=self._host,
                                         user=self._user,
                                         err=err))

    def pull_msgids(self, subject):
        """返回一个字典,字典key为messageid, value为发件人.若没有获取到则为空字典{}"""
        try:
            self._server.select_folder('INBOX')
            msgids = self._server.search(['UNDELETED', 'SUBJECT', subject])
            envelopes = self._server.fetch(msgids, ['ENVELOPE'])
        except Exception as err:
            raise IMAPOperationError(
                "MailPuller.pull_msgids() run error. Message: {err}".format(
                    err=err))
        msgids_with_sender = {}
        for i in msgids:
            msgids_with_sender.update({
                i:
                (envelopes[i][b'ENVELOPE'].sender[0].mailbox.decode('utf-8') +
                 '@' +
                 envelopes[i][b'ENVELOPE'].sender[0].host.decode('utf-8'))
            })
        return msgids_with_sender

    def download(self, msgid):
        """返回 RFC822 格式的 str

        :param msgid: int
        :return: str
        下载(fetch)后,邮件被标记为 SEEN"""
        try:
            return self._server.fetch(
                msgid, ['RFC822'])[msgid][b'RFC822'].decode('utf-8')
        except Exception as err:
            raise IMAPOperationError(
                "MailPuller.download() run error. Message: {err}".format(
                    err=err))

    def delete(self, msgids):
        """将邮件标记为 DELETED, 并未真正删除

        :param msgids: int or list that item is int"""
        self._server.delete_messages(msgids)

    def logout(self):
        try:
            self._server.logout()
        except Exception:
            pass

    def __del__(self):
        # 对象被回收时,自动关闭邮箱服务器的链接
        try:
            self._server.logout()
        except Exception:
            pass
Esempio n. 33
0
#!/home/rajesh/projects/scrapping/web_crawling/bin/python3
from imapclient import IMAPClient
import config

mail = IMAPClient('imap.gmail.com', ssl=True, port=993)
mail.login(config.getMailID(), config.getPasswd())
totalMail = mail.select_folder('Inbox')
#Shows how many messages are there - both read and unread
print('You have total %d messages in your folder' % totalMail[b'EXISTS'])
delMsg = mail.search(('UNSEEN'))
mail.delete_messages(delMsg)
#Shows number of unread messages that have been deleted now
print('%d unread messages in your folder have been deleted' % len(delMsg))
mail.logout()
Esempio n. 34
0
class CuckooRequest(object):

    def __init__(self, message):
        self.message = message
        
        '''cuckooinbox config variables'''
        config = Config(cfg=os.path.join(CUCKOO_ROOT,"cuckooinbox","cuckooinbox.conf"))
        config = config.get('cuckooinbox')
        self.username = config['username']
        self.passwd = config['passwd']
        self.imap = config['imap']
        self.imap_ssl = config['imap_ssl']
        self.smtp_server = config['smtp']
        self.interval = config['interval']
        self.archive_folder = config['archive_folder']
        self.email_whitelist = config['email_whitelist']
        self.url_limit = config['url_limit']
        self.attachment_limit = config['attachment_limit'] 
        self.zip_reports = config['zip_reports']
        self.zip_password = config['zip_password']
        self.url_blacklist = config['url_blacklist']
        self.url_file_backlist = config['url_file_backlist']
        self.machine = config['machine']
        
        '''imap variables'''
        self.server = IMAPClient(self.imap, use_uid=True, ssl=self.imap_ssl)
        self.server.login(self.username, self.passwd)
        self.attachment_counter = 0
        
        '''message variables'''
        self.msg = MIMEMultipart()
        self.response_msg = MIMEMultipart()
        self.response_urls = []
        self.response_attachments = []
        self.sender = ''
        self.subject = ''
        self.cc_list = []

        '''logging object'''
        self.log_entry = Logger('cuckooinbox.log')

        '''cuckoo variables'''
        self.taskids = []
        self.db  = Database()
        self.url_counter = 0 # tracks url count to not exceed url_limit
    
    def fetch(self, message):
        
        '''set retrieve folder'''
        select_info = self.server.select_folder('INBOX')
        '''fetch mail'''
        response = self.server.fetch(self.message, ['RFC822'])
    
        '''parse received email'''
        for msgid, data in response.iteritems():
            msg_string = data['RFC822']
            self.msg = email.message_from_string(msg_string)
            
            '''parse 'Name <*****@*****.**>' format'''
            if '<' in self.msg['From']: self.sender = self.msg['From'].split('<'[0])[-1][:-1]            
            else: self.sender = self.msg['From']
            self.subject = self.msg['Subject']
            
            '''print and log successful receive'''
            self.log_entry.logEvent('[+] Received email ID: %d from %s [%s]' % (msgid, self.msg['From'], self.msg['Subject']))
            
            '''save CC info for reply later'''
            if self.msg['Cc']:
                for address in  self.msg['Cc'].split(', '): self.cc_list.append(address)
                self.log_entry.logEvent( '[*] Email \"%s\" from %s cc\'d the following addresses: %s' % (self.msg['Subject'],self.msg['From'],', '.join(str(copies) for copies in self.cc_list)))
            
            file_whitelist = ['exe', 'doc', 'docx', 'xls', 'xlsx', 'pdf', 'zip']
            
            '''parse message elements'''
            for part in self.msg.walk():
                if part.get_content_type() == 'text/plain':
                    self.log_entry.logEvent( '[*] Email ID: %d has a plain text object.' % msgid)
                    content = part.get_payload()
                    self.processText(content)
                elif part.get_content_type() == 'text/html':
                    self.log_entry.logEvent('[*] Email ID: %d has a html object.' % msgid)
                    content = part.get_payload()
                    self.processText(content)
                elif 'application' in part.get_content_type():
                    # email attachment has no filename
                    if not part.get_param('name'): return 0
                    # cuckoo file analysis whitelist
                    if not part.get_param('name').split('.'[0])[-1] in file_whitelist: break
                    # increment and break if limit is reached 
                    if (self.attachment_limit != 0 and self.attachment_counter == self.attachment_limit): break
                    self.attachment_counter += 1
                    self.log_entry.logEvent('[*] Email ID: %d has an attachment object.' % msgid)
                    content = part.get_payload()
                    file_name = part.get_param('name')
                    self.processAttachment(content, file_name)
                    
            '''archive email when done submitting cuckoo tasks'''
            try:
                self.archive(self.message)
            except:
                self.server.delete_messages(self.message)
                self.server.expunge()

    def processText(self, content):
        
        '''reformat quoted string mail to plain html'''
        body = quopri.decodestring(content)
        soup = BeautifulSoup(body)
        # todo analyze href spoof
        
        '''parse and analyze hyperlinks'''
        for url in soup.findAll('a'):
            # strip mailto links
            if url['href'].split(':'[0])[0] == 'mailto' : continue
            # strip blacklist links
            for item in self.url_blacklist.split(','):
                if item in url['href']: return 0
            # strip blacklist link filetypes
            for item in self.url_file_backlist.split(','):
                if item in url['href'].split('.'[0])[-1]: return 0
            else:
                self.response_urls.append(url['href'])
		if self.machine:
                    task_id = self.db.add_url(url['href'], package="ie", timeout=15, machine=self.machine)
                else: task_id = self.db.add_url(url['href'], package="ie", timeout=15)
                if task_id:
                    self.taskids.append(task_id)
                    self.log_entry.logEvent('[+] URL \"%s\" added as task with ID %d' % (url['href'],task_id))
                    # increment counter and exit loop if limit is reached
                    self.url_counter += 1
                    if (self.url_limit != 0 and self.url_counter == self.url_limit): return 0
                else:
                    self.log_entry.logEvent("[!] Error: adding task to database" % (url['href'],task_id))
                    break

    def processAttachment(self, content, filename):
        '''create temp file for analysis'''
        temp_file = tempfile.NamedTemporaryFile(prefix=filename.split('.'[0])[0], suffix='.' + filename.split('.'[0])[1])
        temp_file.write(content)
        self.response_attachments.append(filename)
        
        '''add to cuckoo tasks'''
        task_id = self.db.add_path(temp_file.name, timeout=10, package=filename.split('.'[0])[1])
        temp_file.flush()
        if task_id:
            self.taskids.append(task_id)
            self.log_entry.logEvent('[+] File \"%s\" added as task with ID %d' % (filename,task_id))
        else:
            self.taskids.append(task_id)
            self.log_entry.logEvent("[!] Error adding task to database")
            
        '''make sure file gets submitted before we toss it'''
        timeout = time.time() + 120
        while time.time() < timeout:
            if os.path.exists(os.path.join(CUCKOO_ROOT,"storage","analyses",str(task_id),"reports","report.html")): continue
            time.sleep(.25)
        temp_file.close()


    def archive(self, message):

        select_info = self.server.select_folder('INBOX')
        '''cleanup mailbox'''
        self.server.copy(self.message,self.archive_folder)
        self.server.delete_messages(self.message)
        self.server.expunge()
        
    def expunge(self, message):

        select_info = self.server.select_folder('INBOX')
        '''expunge cuckooinbox request'''
        self.server.delete_messages(self.message)
        self.server.expunge()


    def zipResults(self,):
        
        '''create temporary zip file'''
        temp_zip = tempfile.TemporaryFile(prefix='report',suffix='.zip')
        zip_file = zipfile.ZipFile(temp_zip, 'w')
        if self.zip_password: zip_file.setpassword(self.zip_password)
        
        '''set zip to compress'''
        try:
            import zlib
            compression = zipfile.ZIP_DEFLATED
        except:
            compression = zipfile.ZIP_STORED
        modes = { zipfile.ZIP_DEFLATED: 'deflated',
                zipfile.ZIP_STORED:   'stored',}
        
        '''wait for reports to finish then add to list'''
        for id in self.taskids:
            # timeout error handling
            if not os.path.exists(os.path.join(CUCKOO_ROOT,"storage","analyses",str(id),"reports","report.html")):
                self.log_entry.logEvent('cuckooinbox error: report timeout reached on task ID %d.' % id)
            else: 
                zip_file.write(os.path.join(CUCKOO_ROOT,"storage","analyses",str(id),"reports","report.html"),\
                arcname = 'report' + str(id) + '.html', compress_type=compression)
        zip_file.close()
            
        '''attach zip to email message'''
        temp_zip.seek(0)
        email_file = MIMEBase('application', 'zip')
        email_file.set_payload(temp_zip.read())
        Encoders.encode_base64(email_file)
        email_file.add_header('Content-Disposition', 'attachment; filename="report.zip"')
        self.response_msg.attach(email_file)

    def sendReport(self,):

        '''create email header'''
        assert type(self.cc_list)==list
        assert type(self.taskids)==list
        self.response_msg['From'] = self.username
        self.response_msg['To'] = self.sender
        self.response_msg['Cc'] = ", ".join(self.cc_list)
        self.response_msg['Date'] = formatdate(localtime=True)
        self.response_msg['Subject'] = 'cuckooinbox report: ' + self.subject

        '''attach cuckooinbox email body'''
        for id in self.taskids:
	    '''wait for reports to finish before sending'''
	    timeout = time.time() + 120
            while time.time() < timeout:
                if os.path.exists(os.path.join(CUCKOO_ROOT,"storage","analyses",str(id),"reports","report.html")): continue
            	time.sleep(.25)
            if os.path.exists(os.path.join(CUCKOO_ROOT,"storage","analyses",str(id),"reports","inbox.html")):
                file = open(os.path.join(CUCKOO_ROOT,"storage","analyses",str(id),"reports","inbox.html"))
                body = '<html>' + \
                    '<div class="section-title">'+ \
                    '<h2>Task ID %d <small></small></h2>' % id + \
                    '</div>'+ \
                    '<table class="table table-striped table-bordered">'+ \
                    file.read() + \
                    '</html>'
                file.close()
                response_text = ''.join(body)
                self.response_msg.attach(MIMEText(response_text,'html'))
            else: print '[!] Could not find cuckoobox report files.'

        '''wait for analysis to finish and zip the reports'''
        self.zipResults()
        
        '''send the message'''
	if '@gmail.com' in self.username:
	    smtp = smtplib.SMTP('smtp.gmail.com',587)
	    smtp.starttls()
	    smtp.login(self.username, self.passwd)
	else:
            smtp = smtplib.SMTP(self.smtp_server)
            try: smtp.login(self.username,self.passwd)
            except:
                self.log_entry.logEvent('[!] SMTP login failed.')
        try: smtp.sendmail(self.username, self.sender, self.response_msg.as_string())
        except:
            self.log_entry.logEvent('SMTP message %s failed to send.' % self.subject)
        smtp.close()
        self.log_entry.logEvent('[-] Sent "%s" report to %s' % (self.subject, self.sender))
        self.server.logout()
Esempio n. 35
0
class Imapmail(object):
    '''
    定义类Imapmail实现代理登录邮箱,监听,获取往期邮件等功能
    '''
    def __init__(self):  # 初始化数据
        self.ID = 0
        self.server_address = None  # imap地址 例如imap.163.com
        self.user = None  # 邮箱账号
        self.password = None  # 邮箱密码
        self.prot = None
        self.ssl = None
        self.timeout = None  # 连接超时最大时间

        self.server = None  # imap客户端 用于与imap服务器交互
        self.result = list()  # 某标签(ALL,UNSEEN等)的全部邮件
        self.size = 0  # 邮件的数量
        self.previous = 0  # 上一次扫描邮件的数量
        self.messageObj = None  # 存储单封邮件的内容

        self.received_mails = {'垃圾邮件': list(), '正常邮件': list()}  # 存储往期邮件

        global white_list
        global black_list

        # 获取与该用户绑定的个人白名单和黑名单
        # 加载本地白名单 黑名单
        pickle_file_white = open('white_list.pkl', 'rb')
        white_list = pickle.load(pickle_file_white)
        pickle_file_black = open('black_list.pkl', 'rb')
        black_list = pickle.load(pickle_file_black)


    def client(self):  # 链接imap服务器 得到server
        try:
            self.server = IMAPClient(self.server_address, self.prot, self.ssl, timeout=self.timeout)
            return self.server
        except BaseException as e:
            return "ERROR: >>> " + str(e)

    def login(self):  # 邮箱登录
        try:
            self.server.login(self.user, self.password)
            global save_paths
            #  加载附件下载地址
            pickle_file_save_path = open('save_paths.pkl', 'rb')
            save_paths = pickle.load(pickle_file_save_path)
            #  附件下载地址
            if self.user not in save_paths.keys():
                save_paths.update({self.user: '******'})
                pickle_file = open('save_paths.pkl', 'wb')
                pickle.dump(save_paths, pickle_file)
                pickle_file.close()

        except BaseException as e:
            return 0

    def get_mail_dir(self):  # 获取邮箱目录 暂不使用
        # 获取目录列表 [((), b'/', 'INBOX'), ((b'\\Drafts',), b'/', '草稿箱'),]
        dir_list = self.server.list_folders()
        return dir_list

    def init(self):  # 监听机制初始化 设置初始邮件数量
        self.server.select_folder('INBOX', readonly=False)  # 选择目录 readonly=True 只读,不修改,这里只选择了 收件箱
        self.result = self.server.search('all')  # 获取所有邮件总数目 [1,2,3,....]
        self.previous = len(self.result)

    def get_result(self):  # 循环监听 更改邮件数量
        #  self.server.select_folder('INBOX', readonly=False)  # 选择目录 readonly=True 只读,不修改,这里只选择了 收件箱
        self.result = self.server.search('all')  # 获取所有邮件总数目 [1,2,3,....]
        self.size = len(self.result)
        return self.size

    def if_exist_attach(self, mg):
        msg_dict = self.server.fetch(mg, ['BODY[]'])  # 获取邮件内容
        mail_body = msg_dict[mg][b'BODY[]']  # 获取邮件内容
        message = pyzmail.PyzMessage.factory(mail_body)
        flag = 0
        for part in message.mailparts:
            if part.filename:
                flag = 1
        if flag == 1:
            return 1
        else:
            return 0

    def get_attach(self, mg):  # 获取附件
        global save_paths
        if not os.path.exists(save_paths[self.user]):  # 判断下载目录是否存在,不存在就创建一个
            os.mkdir(save_paths[self.user])
        msg_dict = self.server.fetch(mg, ['BODY[]'])  # 获取邮件内容
        mail_body = msg_dict[mg][b'BODY[]']  # 获取邮件内容
        message = pyzmail.PyzMessage.factory(mail_body)
        num = 0
        for part in message.mailparts:
            if part.filename:
                num += 1
                filename_save = message.get_address('from')[1] + '_' + part.filename
                down_path = os.path.join(save_paths[self.user], filename_save)
                #  print('附件保存地址为:%s' % down_path)
                with open(down_path, 'wb') as f:
                    f.write(part.get_payload())
                #  print('下载完毕')

    def get_content(self, mg):
        data = self.server.fetch(mg, ['ENVELOPE'])
        envelope = data[mg][b'ENVELOPE']
        dates = envelope.date
        msg_dict = self.server.fetch(mg, ['BODY[]'])  # 获取邮件内容
        mail_body = msg_dict[mg][b'BODY[]']  # 获取邮件内容
        ip = (re.search(
            r'(?:(?:[01]?\d?\d?|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d?\d?|2[0-4]\d|25[0-5])',
            str(mail_body))).group()
        self.messageObj = pyzmail.PyzMessage.factory(mail_body)
        subject = self.messageObj.get_subject()
        send = str(self.messageObj.get_addresses('from')[0][1])
        send_time = str(dates)
        message_Content = '内容为空'
        mail = {'垃圾': 0, '主题': subject, '发件人': send, '时间': send_time,
                'IP地址': ip, '主要内容': message_Content, '邮件': None, '附件': 0}
        if self.if_exist_attach(mg):
            mail['附件'] = 1
        else:
            mail['附件'] = 0
        self.ID += 1
        if self.messageObj.text_part is not None:
            message_Content = self.messageObj.text_part.get_payload().decode(self.messageObj.text_part.charset)
            mail['主要内容'] = message_Content
        # if self.messageObj.html_part is not None:
        #   message_Content = self.messageObj.html_part.get_payload().decode(self.messageObj.text_part.charset)
        #    mail['主要内容'] = message_Content
        else:
            pass
        return mail

    def get_new_mail(self,normDict, spamDict,health_dic, spam_dic, health_sum, spam_sum):  # 监听最新邮件
        count = 0
        self.get_result()
        mails = list()
        temp = self.previous  # 11
        count = len(self.result) - self.previous
        self.previous = len(self.result)
        if count == 0:
            print('邮件总数:' + str(self.size))
        else:
            print('邮件总数:' + str(self.size))
            for each_mail in self.result[temp:self.size]:
                mail = self.get_content(each_mail)
                mail['邮件'] = each_mail
                if mail['发件人'] in white_list:
                    pass
                elif mail['发件人'] in black_list:
                    #  self.previous -= 1
                    mail['垃圾'] = 1
                    mails.append(mail)
                    self.send_back(mail)
                else:
                    # 由公共黑名单或者算法进行判断
                    # 根据结果更新词条垃圾的值
                    # 云端判断邮件垃圾与否
                    chnum, ennum, allnum, chp = self.number(mail['主要内容'])
                    if chp > 0.9:
                        div = filter2.Get_Email_Div(mail['主要内容'])
                        result = filter2.Get_Bayes_Num(div, spamDict, normDict, 7063, 7775)
                    else:
                        result = filter2.Bayes(mail['主要内容'], ennum,health_dic, spam_dic, health_sum, spam_sum)

                    if result == 1:
                        mail['垃圾'] = 1
                        #  self.send_back(mail)
                    else:
                        pass
                    mails.append(mail)
        return mails

    def delete_mail(self, mail):
        self.server.delete_messages(mail)

    def get_all_mails(self, normDict, spamDict,health_dic, spam_dic, health_sum, spam_sum):
        self.get_result()
        if self.size == 0:
            print('收件箱为空')
        else:
            for each_mail in self.result:
                mail = self.get_content(each_mail)
                mail['邮件'] = each_mail
                temp = mail.copy()
                temp.pop('邮件')
                temp.pop('垃圾')
                if temp in Lgmail.extra_list:
                    mail['垃圾'] = 0
                    self.received_mails['正常邮件'].append(mail)
                elif mail['发件人'] in white_list:
                    self.received_mails['正常邮件'].append(mail)
                elif mail['发件人'] in black_list:
                    mail['垃圾'] = 1
                    self.received_mails['垃圾邮件'].append(mail)
                else:
                    # 由公共黑名单或者算法进行判断
                    # 由公共黑名单或者算法进行判断
                    # 根据结果更新词条垃圾的值
                    chnum, ennum, allnum,chp = self.number(mail['主要内容'])
                    if chp>0.8:
                        #  div = filter2.Get_Email_Div(mail['主要内容'])
                        #  result = filter2.Get_Bayes_Num(div, spamDict, normDict, 7063, 7775)
                        pass
                    else:
                        #  result = filter2.Bayes(mail['主要内容'],ennum,health_dic, spam_dic, health_sum, spam_sum)
                        pass
                    result = 1
                    if result == 1:
                        mail['垃圾'] = 1
                        self.received_mails['垃圾邮件'].append(mail)
                    else:
                        self.received_mails['正常邮件'].append(mail)
                        #  self.get_attach(each_mail)
        return self.received_mails

    def number(self, content):
        allnum = 0
        chnum = 0
        ennum = 0
        for i in content:
            if '\u4e00' <= i <= '\u9fff':
                chnum += 1
                allnum += 1
            if (i >= u'\u0041' and i <= u'\u005a') or (i >= u'\u0061' and i <= u'\u007a'):
                ennum += 1
                allnum += 1
        chp = chnum / allnum
        return chnum, ennum, allnum, chp

    def close(self):  # 断开连接
        self.server.logout()

    def add_white(self, name):  # 添加本地白名单
        global white_list
        if name not in white_list:
            white_list.append(name)
            pickle_file = open('white_list.pkl', 'wb')
            pickle.dump(self.white_list, pickle_file)
            pickle_file.close()

    def add_black(self, name):  # 添加本地黑名单
        global black_list
        if name not in black_list:
            black_list.append(name)
            pickle_file = open('white_list.pkl', 'wb')
            pickle.dump(self.black_list, pickle_file)
            pickle_file.close()

    def send_back(self, mail):  # 自动恢复垃圾邮件
        sender_user = self.user  # 自动回复的发件人
        sender_password = self.password  # 密码
        sender_smtp = 'smtp.'+self.user.split('@')[-1]  # 发送方的smtp地址
        receive_user = mail['发件人']  # 收件人的邮箱地址
        message = MIMEText('你这个辣鸡', 'plain', 'utf-8')  # 邮件对象
        message['From'] = sender_user  # 设置发件人
        message['TO'] = receive_user  # 设置收件人
        message['Subject'] = '测试邮件'  # 设置主题
        with SMTP_SSL(host=sender_smtp, port=465) as smtp:
            # 连接smtp服务器
            smtp.login(user=sender_user, password=sender_password)
            smtp.sendmail(from_addr=self.user, to_addrs=receive_user, msg=message.as_string())
            smtp.quit()
Esempio n. 36
0
File: bot.py Progetto: rca/imapbot
class IMAPBot(object):
    IMAPBotError = IMAPBotError

    def __init__(self, host, username, password, ssl=True):
        self.server = IMAPClient(host, use_uid=True, ssl=ssl)
        self.server.login(username, password)

        if 'IDLE' not in self.server.capabilities():
            raise IMAPBotError('Sorry, this IMAP server does not support IDLE.')

        # the folder where processed emails go
        self.processed_folder = 'imapbot_processed'

        self.idle_timeout = 5  # seconds

        self._is_idle = False
        self._run = True

        self._create_folder(self.processed_folder)

    def check_mail(self):
        select_info = self.server.select_folder('INBOX')
        print '%d messages in INBOX' % select_info['EXISTS']

        messages = self.server.search(['UNSEEN'])
        messages = self.server.search(['NOT DELETED'])
        print "%d messages that haven't been seen" % len(messages)

        if not messages:
            return

        #response = self.server.fetch(messages, ['FLAGS', 'INTERNALDATE', 'RFC822.SIZE', 'ENVELOPE', 'RFC822.TEXT'])
        response = self.server.fetch(messages, ['FLAGS', 'ENVELOPE', 'RFC822.TEXT'])
        for message_id, data in response.iteritems():
            message = Message(message_id, data['ENVELOPE'], data['RFC822.TEXT'], data['FLAGS'])

            self.process(message)

    def complete(self, message):
        message_ids = [message.id]

        self.server.copy(message_ids, self.processed_folder)
        self.server.delete_messages(message_ids)
        self.server.expunge()

    def _create_folder(self, name):
        # make sure the folder doesn't already exist
        if self.server.folder_exists(name):
            return

        self.server.create_folder(name)

    def handle_message(self, message):
        print 'message id: {}, from: {}:'.format(message.id, message.envelope.get_email('from'))
        with open('message.txt', 'ab') as fh:
            fh.write('{}\n\n'.format(message.text))

        print message.plain or message.html or 'no message'

    def idle(self):
        if self._is_idle:
            return

        self.server.idle()

        self._is_idle = True

        return True  # this actually changed state

    def unidle(self):
        if not self._is_idle:
            return

        self.server.idle_done()

        self._is_idle = False

        return True  # this call actually changed state

    def process(self, message):
        self.handle_message(message)
        self.complete(message)

    def run(self):
        # process any mail that was in the inbox before coming online
        self.check_mail()

        # put the connection in idle mode so we get notifications
        self.idle()

        # loop forever looking for stuff
        while self._run:
            for message in self.server.idle_check(timeout=self.idle_timeout):
                if message[0] == 'OK':
                    continue

                with Unidle(self):
                    self.check_mail()

    def quit(self):
        self._run = False

        self.unidle()

        print self.server.logout()
Esempio n. 37
0
def main():
	# -options-
	parser = OptionParser("python %prog [options] CONFIG_FILE")
	parser.add_option('-v', '--verbose', action='store_true', dest='verbose', default=False)
	(options, args) = parser.parse_args()

	# -settings-
	if len(args) < 1:
		parser.print_help()
		exit()

	if not os.path.exists(args[0]):
		raise IOError(ENOENT, 'Archivo de configuracion no encontrado', args[0])

	config = RawConfigParser()
	config.read(args[0])
	# put read config options (from the .ini) into global namespace and in uppercase
	for name, value in config.items('chkemail'):
		globals()[name.upper()] = value

	# -workflow-
	# create, connect, and login to server
	server = IMAPClient(HOST, use_uid=True)
	try:
		server.login(USER, PASSWORD, port=PORT)
	except NameError: # if PORT is not defined
		server.login(USER, PASSWORD)

	inbox = server.select_folder('INBOX')
	if options.verbose:
		print '%d messages in INBOX (included deleted)' % inbox['EXISTS']

	messages = server.search(['NOT DELETED', 'HEADER Content-Type mixed'])
	if options.verbose:
		print "%d messages with possible attch" % len(messages)

	# fetch data from messages, put each message (Mess object) into the msgs list
	scan = server.fetch(messages, ['BODYSTRUCTURE', 'ENVELOPE'])
	msgs = dict()
	for mid, response in scan.iteritems():
		# Mess class only works with mulipart messages
		if response['BODYSTRUCTURE'].is_multipart:
			msgs[mid] =  Mess(mid, response['ENVELOPE'], response['BODYSTRUCTURE'])

	# Select the messages with attachements I want, put them in group_msgs
	group_msgs = dict()
	for msg in msgs.itervalues():
		group_msgs[msg.id] = list()
		for part_num, part_info in msg.parts.iteritems():
			if part_info.filename:
				filename = part_info.filename.lower()
				if filename.endswith('.pdf') or filename.endswith('.xml') or \
					filename.endswith('.zip'):
					group_msgs[msg.id] += [part_num]
		if not group_msgs[msg.id]:
			del group_msgs[msg.id]

	# fetch all interesting parts
	for msg_id, parts in group_msgs.iteritems():
		request = ['BODY['+str(part)+']' for part in parts]
		response = server.fetch(msg_id, request)
		for body_part in response[msg_id].iterkeys():
			if 'BODY' in body_part:
				msgs[msg_id].parts[body_part[5:-1]].data = response[msg_id][body_part]

	# move messages to trash
	if len(group_msgs.keys()) > 0:
		server.copy(group_msgs.keys(), 'INBOX.Trash')
		server.delete_messages(group_msgs.keys())
	server.logout()

	# ensure there's an OUTPUT_DIR directory
	pdf_dir = os.path.join(OUTPUT_PDF, strftime('%Y-%m'))
	ensure_dir(pdf_dir)
	ensure_dir(OUTPUT_DIR)

	# decode and write data to file
	num_attch = 0
	for msg in msgs.itervalues():
		for part in msg.parts:
			if part.data:
				filename = part.filename.lower()
				if filename.endswith('.pdf') or filename.endswith('.xml'):
					if filename.endswith('.pdf'):
						ensure_dir(os.path.join(pdf_dir, str(msg.envelope)))
						attachment_filename = generate_filename(os.path.join(pdf_dir, str(msg.envelope), os.path.basename(part.filename)))
					else:
						attachment_filename = generate_filename(os.path.join(OUTPUT_DIR, os.path.basename(part.filename)))
					with open(attachment_filename, 'wb') as file_:
						if part.encoding == 'quoted-printable':
							file_.write(decodestring(part.data))
						elif part.encoding == 'base64':
							file_.write(b64decode(part.data))
					num_attch += 1
				elif filename.endswith('.zip') and part.encoding == 'base64':
					with tempfile.TemporaryFile() as tmp_zip:
						tmp_zip.write(b64decode(part.data))
						zip_file = ZipFile(tmp_zip)
						for f_info in zip_file.infolist():
							if f_info.filename.lower().endswith('.xml'):
								attachment_filename = generate_filename(os.path.join(OUTPUT_DIR, os.path.basename(f_info.filename)))
							elif f_info.filename.lower().endswith('.pdf'):
								ensure_dir(os.path.join(pdf_dir, str(msg.envelope)))
								attachment_filename = generate_filename(os.path.join(pdf_dir, str(msg.envelope), os.path.basename(f_info.filename)))
							else:
								continue
							with open(attachment_filename, 'wb') as file_:
								file_.write(zip_file.read(f_info))
							num_attch += 1

	if options.verbose:
		print '%d files extracted' % num_attch
Esempio n. 38
0
class SourceDriverMail(SourceDriver):
    def __init__(self, instanceName: str, settings: Settings,
                 parser: MessageParser) -> None:
        super().__init__("mail", instanceName, settings, parser)
        # Settings
        self.__server = self.getSettingString("server", "")
        self.__user = self.getSettingString("user", "")
        self.__password = self.getSettingString("password", "")
        self.__ssl = self.getSettingBoolean("ssl", True)
        self.__fix_weak_dh = self.getSettingBoolean("fix_weak_dh", False)
        self.__allowlist = self.getSettingList("allowlist", [])
        self.__denylist = self.getSettingList("denylist", [])
        self.__cleanup = self.getSettingString("cleanup", "")
        self.__archive_folder = self.getSettingString("archive_folder",
                                                      "Archive")

        if self.__cleanup == "Delete":
            self.print("Cleanup strategy is delete")
        elif self.__cleanup == "Archive":
            self.print("Cleanup strategy is archive")
        elif self.__cleanup == "":
            self.print("Cleanup is disabled")
        else:
            self.fatal("Unknown cleanup strategy")

        # Internal
        self.__healthy = False

        self.__connect()

    def retrieveEvent(self) -> Optional[SourceEvent]:
        try:
            if self.isDebug():
                self.print("Checking for new mails")
            messages = self.__imap_client.search('UNSEEN')
            for uid, message_data in self.__imap_client.fetch(
                    messages, "RFC822").items():
                message = email.message_from_bytes(message_data[b"RFC822"],
                                                   policy=policy.default)
                sender = parseaddr(message.get("From"))[1]
                sourceEvent = SourceEvent()
                sourceEvent.source = SourceEvent.SOURCE_MAIL
                sourceEvent.timestamp = datetime.datetime.strptime(
                    message.get('Date'), "%a, %d %b %Y %H:%M:%S %z").strftime(
                        SourceEvent.TIMESTAMP_FORMAT)
                sourceEvent.sender = sender
                sourceEvent.raw = message.get_body(('plain', )).get_content()
                if self.isSenderAllowed(allowlist=self.__allowlist,
                                        denylist=self.__denylist,
                                        sender=sender):
                    parsedSourceEvent = self.parser.parseMessage(
                        sourceEvent, None)  # type: ignore[union-attr]
                    self.__do_cleanup(uid)
                    return parsedSourceEvent
                else:
                    self.error("Received unhandled message (ignored sender)")
                    return UnhandledEvent.fromSourceEvent(
                        sourceEvent, UnhandledEvent.CAUSE_IGNORED_SENDER)
        except (timeout, OSError) as e:
            self.error("Connection to mailserver timed out")
            self.__healthy = False
            self.__connect()

    def getSourceState(self) -> SourceState:
        if self.__healthy:
            return SourceState.OK
        return SourceState.ERROR

    def __connect(self):
        if self.__fix_weak_dh:
            context = ssl.SSLContext(
                ssl.PROTOCOL_TLSv1_2)  # Workaround for weak dh key
            context.set_ciphers('DEFAULT@SECLEVEL=1')
        else:
            context = ssl.SSLContext()

        try:
            if self.isDebug():
                self.print("Connecting to server {}".format(self.__server))
            self.__imap_client = IMAPClient(self.__server,
                                            use_uid=True,
                                            ssl=self.__ssl,
                                            ssl_context=context,
                                            timeout=1.0)
        except gaierror:
            self.error("Failed to connect to Mail Server")
        except ssl.SSLError:
            self.fatal("Failed to connect to Mail Server (TLS Error)")
        else:
            try:
                if self.isDebug():
                    self.print("Login as user {}".format(self.__user))
                self.__imap_client.login(self.__user, self.__password)
            except LoginError:
                self.error("Mail Server login failed")
            else:
                if self.isDebug():
                    self.print("Login successful")
                self.__healthy = True
                self.__imap_client.select_folder('INBOX', readonly=False)

    def __create_imap_folder(self, folder):
        if not self.__imap_client.folder_exists(folder):
            self.print("Folder {} does not exist creating")
            self.__imap_client.create_folder(folder)

    def __do_cleanup(self, uid):
        if self.__cleanup == "Archive":
            self.__create_imap_folder(self.__archive_folder)
            self.__imap_client.copy(uid, self.__archive_folder)
        if self.__cleanup == "Delete" or self.__cleanup == "Archive":
            self.__imap_client.delete_messages(uid)
            self.__imap_client.expunge(uid)
Esempio n. 39
0
class EmailClient(object):
    def __init__(self, config):
        """
        Create an email client abstraction configured for an account.

        config is a dict with keys:
            HOST
            USERNAME
            PASSWORD
            USE_SSL default=True
            FOLDER default='INBOX'
            SELECTORS default=['NOT DELETED']
        """
        self.config = {
            'USE_SLL': True,
            'FOLDER': 'INBOX',
            'SELECTORS': ['NOT DELETED']
        }
        self.config.update(config)

    def connect(self):
        self.server = IMAPClient(self.config['HOST'],
                                 use_uid=True,
                                 ssl=self.config['USE_SSL'])
        self.server.login(self.config['USERNAME'], self.config['PASSWORD'])
        select_info = self.server.select_folder(self.config['FOLDER'])

    def process_new_messages(self, debug=False):
        """
        Get mesages from the server.

        Note: new information on existing uids will be ignored.
        For example, if the rfc_size changes (which is a strangely common occurrence),
        the new value will be ignored.
        """
        if debug: print "searching"
        messages = self.server.search(self.config['SELECTORS'])
        if debug: print "done searching"
        self._process_messages(messages, debug=debug)

    def _process_messages(self, uids, move=False, debug=False):
        if debug: print "fetching"
        response = self.server.fetch(uids, ['FLAGS', 'RFC822', 'RFC822.SIZE'])
        for msg_uid, data in response.iteritems():
            if debug: print "processing %s" % msg_uid
            with transaction.commit_on_success():
                # extract data
                flags = data['FLAGS']
                rfc_size = data['RFC822.SIZE']
                raw_body = data['RFC822']
                seq = data['SEQ']

                # save objects
                email, _ = EmailMessage.objects.get_or_create(
                    uid=msg_uid,
                    username=self.config['USERNAME'],
                    host=self.config['HOST'],
                    defaults={
                        'raw_body': raw_body,
                        'rfc_size': rfc_size,
                        'seq': data['SEQ'],
                    })

                email.save()

                for flag in flags:
                    EmailFlag.objects.get_or_create(email=email,
                                                    flag=flag)[0].save()

                # move message
                if move:
                    self.server.copy([msg_uid], 'auto_processed')
                    self.server.delete_messages([msg_uid])
Esempio n. 40
0
            commstr = commstr.strip()
            logging.debug('COMMAND: ' + commstr)
            comm = commstr.split(' ')
            comm[0] = comm[0].lower()
            if comm[0] == 'quit':
                for i in range(2):
                    inst_queue.put([['quit'], listener, talker, passw, 0])
                ch = 1
                break
            else:
                inst_queue.put([comm, listener, talker, passw, 0])

            if ch == 1:
                inst_queue.join()
                break
    imapobj.delete_messages(UIDs)
    UIDs = []

try:
    smtpobj = smtplib.SMTP('smtp.gmail.com', 587)
    smtpobj.ehlo()
    smtpobj.starttls()
    smtpobj.login(listener, passw)
    smtpobj.sendmail(listener, talker, 'Subject:ALFRED OFFLINE. THANK YOU\n')
    imapobj.logout()
    smtpobj.quit()

except smtplib.SMTPAuthenticationError:
    print 'incorrect login credentials'
    logging.debug('listener logging failed')
Esempio n. 41
0
class EmailOperation(object):
    def __init__(self, user_name, pwd):
        print("使用imapclient,操作邮件...")
        self.server = IMAPClient('imap.139.com', use_uid=True, ssl=False)
        self.username = user_name
        self.password = pwd

    def logout(self):
        self.server.logout()

    # 删除邮件
    def _del(self, messages):
        #         print('del message')
        self.server.delete_messages(messages)
        self.server.expunge()

    def _mv(self, message, folder):
        self.server.copy(message, folder)
        time.sleep(1)
        self._del(message)

    def _into(self, box):
        # 'INBOX','草稿箱','已发送','已删除','100'
        self.server.select_folder(box)

    def _get_uids(self):
        # 获取序列
        uids = self.server.search(['NOT', 'DELETED'])
        return uids

    def email_body(self, mss):
        # 获取某序列id的原始信息
        raw_messages = self.server.fetch([mss], ['BODY[]', 'FLAGS'])
        #         pprint.pprint(rawMessages)
        # 使用pyzmail,返回主体信息
        message = pyzmail.PyzMessage.factory(raw_messages[mss][b'BODY[]'])

        # 如果信息为空,返回None
        if not message:
            return None
        # 获取正文内容
        if message.text_part != None:
            lines = message.text_part.get_payload().decode(
                message.text_part.charset)

        str = ''
        # 去除内容中的回车
        for line in lines:
            if line not in ['\n', '\r']:
                str += line

        print(str)
        # body自动
        body = {
            'subject': message.get_subject(),
            'from': message.get_address('from'),
            'to': message.get_address('to'),
            'mainbody': str
        }
        return body

    def del_all_message(self, folder):
        '''清空某个文件夹下的所有邮件'''
        self._into(folder)

        uids = self._get_uids()
        if len(uids) == 0:
            return
        else:
            self._del(uids)

    def del_new_message(self, fforlder):
        '''把最近一封新邮件已到目的目录'''
        self._into(fforlder)

        uids = self._get_uids()

        if len(uids) == 0:
            return
        else:
            self._del(uids[-1])

    def move_all_message_to_folder(self, fforlder, tforlder):
        '''把maessage/messages 从 ffolder 移动到 tforlder'''

        self._into(fforlder)

        uids = self._get_uids()
        # 邮件数量为空
        if len(uids) == 0:
            print("%s 数量为:0,该操作无效" % fforlder)
            return True
        self._mv(uids, tforlder)

    def check_new_message(self):
        '''判断最新一封邮件,是否包含某个字段,显示邮件数量'''
        self._into("INBOX")

        uids = self._get_uids()

        print('current INBOX email: %s' % str(len(uids)))

        if len(uids) in [0, 1]:
            print("不执行,目前邮件数量为:%r" % len(uids))
            return

        if self.email_body(uids[-1])['subject'] == 'testReceive':
            self._del(uids[-1])

    def delete_newest_mail(self):
        '''删除最新的一封邮件'''
        try:
            is_true = False
            self.server.login(self.username, self.password)
            self.del_new_message('INBOX')
            is_true = True
        except BaseException as error:
            print(error)
            print("删除邮件可能出现错误")
        finally:
            self.logout()
            return is_true

    def clear_forlder(self, l=[]):
        '''清空邮箱某个文件夹'''
        '''
        sample:
        clearForlder(['100', 'INBOX'])
        '''
        is_true = False
        if len(l) == 0:
            return is_true
        try:
            self.server.login(self.username, self.password)
            for f in l:
                print("clear Forlder: %s" % f)
                self.del_all_message(f)
                time.sleep(1)

            is_true = True
        except BaseException as error:
            print(error)
            print("删除邮件可能出现错误")
        finally:
            self.logout()
            return is_true

    def move_forlder(self, l=[]):
        '''移动邮件
        sample:
            moveForlder(['100', 'INBOX'])
        '''
        is_true = False
        if len(l) == 0:
            return is_true
        try:
            self.server.login(self.username, self.password)
            self.move_all_message_to_folder(l[0], l[1])
            print("移动邮件成功:%s => %s" % (l[0], l[1]))
            is_true = True
        except BaseException as error:
            print(error)
            print("清空邮箱某个文件夹可能出现错误")
        finally:
            self.logout()
            return is_true

    def check_inbox_cnt(self):
        '''获取邮件数量'''
        try:
            is_true = 0
            self.server.login(self.username, self.password)

            self._into("INBOX")
            uids = self._get_uids()
            # 数量为 0
            if len(uids) == 0:
                return 0
            # 判断
            if len(uids) == 100:
                print("100封邮件")
                return 0
            elif len(uids) < 100:
                print('邮件数量少于100封')
                return 0
            else:
                cnt = len(uids) - 100
                print('需要删除邮件数量为:%d' % cnt)
                is_true = cnt
        except BaseException as error:
            print(error)
            print("删除邮件可能出现错误")
        finally:
            self.logout()
            return is_true

    def check_inbox(self):
        '''确保收件箱有100封邮件'''
        try:
            is_true = True
            self.server.login(self.username, self.password)

            self._into("INBOX")
            uids = self._get_uids()
            all = len(uids)
            # 数量为 0
            if all == 0:
                return False
            # 判断
            if all == 100:
                print("100封邮件")
                return is_true
            elif all < 100:
                print('邮件数量少于100封')
                return False
            else:
                print('需要删除邮件数量为:%d' % (all - 100))
                #                 print(Uids[100:])
                self._del(uids[100:])
                return is_true
        except BaseException as error:
            print(error)
            print("删除邮件可能出现错误")
            is_true = False
        finally:
            self.logout()
            return is_true

    def seen(self):
        '''将收件箱邮件,标记已读'''
        self.server.login(self.username, self.password)
        self._into("INBOX")
        # 搜索 未读邮件
        typ = self.server.search([u'UNSEEN'])
        # 把邮件改为已读
        for num in typ:
            print(num)
            self.server.set_flags(num, [u'Seen'])
Esempio n. 42
0
class IMAP():
    """
    Central class for IMAP server communication
    """
    Retval = namedtuple('Retval', 'code data')

    def __init__(self, logger, username, password,
                 server='localhost',
                 port=143,
                 starttls=False,
                 imaps=False,
                 tlsverify=True,
                 test=False,
                 timeout=None):
        self.logger = logger
        self.username = username
        self.password = password
        self.server = server
        self.port = port
        self.imaps = imaps
        self.starttls = starttls
        self.timeout = timeout

        self.sslcontext = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)  # TODO add proto arg
        if tlsverify:
            self.sslcontext.verify_mode = ssl.CERT_REQUIRED
        else:
            self.sslcontext.verify_mode = ssl.CERT_NONE  # TODO improve?

        self.test = test

        self.conn = None

    def do_select_mailbox(func):
        """
        Decorator to do a fresh mailbox SELECT
        """

        def wrapper(*args, **kwargs):
            if len(args) != 1:
                raise AttributeError(
                    'Size of *args tuple "{0}" isn\'t 1. It looks like you haven\'t specified all '
                    'method arguments as named arguments!'.format(
                        args))

            mailbox = None
            for key in ['mailbox', 'source']:
                if key in kwargs.keys():
                    mailbox = kwargs[key]
                    break

            if mailbox is None:
                raise KeyError('Unable to SELECT a mailbox, kwargs "{0}" doesn\'t contain a mailbox name'.format(kwargs))

            result = args[0].select_mailbox(mailbox)
            if not result.code:
                raise RuntimeError(result.data)
            return func(*args, **kwargs)

        return wrapper

    def process_error(self, exception, simple_return=False):
        """
        Process Python exception by logging a message and optionally showing traceback
        """
        trace_info = exc_info()
        err_msg = str(exception)

        if isinstance(exception, IMAPClient.Error):
            err_msg = Helper().byte_to_str(exception.args[0])

        self.logger.error('Catching IMAP exception %s: %s', type(exception), err_msg)

        if self.logger.isEnabledFor(loglevel_DEBUG):
            print_exception(*trace_info)
        del trace_info

        if simple_return:
            return exception
        else:
            return self.Retval(False, err_msg)

    def connect(self, retry=True, logout=False):
        """
        Connect to IMAP server and login
        """
        if self.starttls:
            self.logger.debug('Establishing IMAP connection using STARTTLS/%s to %s and logging in with user %s', self.port, self.server,
                              self.username)
        elif self.imaps:
            self.logger.debug('Establishing IMAP connection using SSL/%s (imaps) to %s and logging in with user %s', self.port, self.server,
                              self.username)

        login = ''
        err_return = None
        try:
            self.conn = IMAPClient(host=self.server,
                                   port=self.port,
                                   use_uid=True,
                                   ssl=self.imaps,
                                   ssl_context=self.sslcontext,
                                   timeout=self.timeout)

            if self.starttls:
                self.conn.starttls(ssl_context=self.sslcontext)

            login = self.conn.login(self.username, self.password)
            login_response = Helper().byte_to_str(login)

            # Test login/auth status
            login_success = False
            noop = self.noop()
            if noop.code and noop.data:
                login_success = True

            if logout:
                return self.disconnect()
            elif login_success:
                return self.Retval(True, login_response)
            else:
                return self.Retval(False, login_response)  # pragma: no cover

        except Exception as e:
            err_return = self.process_error(e)

            if err_return.data == '[AUTHENTICATIONFAILED] Authentication failed.':
                return err_return

            if retry:
                self.logger.error('Trying one more time to login')
                sleep(2)
                return self.connect(retry=False, logout=logout)
            return err_return

    def noop(self):
        """
        Do a noop to test login status
        """
        try:
            noop = self.conn.noop()
            noop_response = Helper().byte_to_str(noop[0])
            noop_resp_pattern_re = regex_compile('^(Success|NOOP completed)')
            login_success = noop_resp_pattern_re.match(noop_response)
            return self.Retval(True, login_success)
        except IMAPClient.Error as e:
            return self.process_error(e)

    def disconnect(self):
        """
        Disconnect from IMAP server
        """
        result = self.conn.logout()
        response = Helper().byte_to_str(result)
        return self.Retval(response == 'Logging out', response)

    def list_mailboxes(self, directory='', pattern='*'):
        """
        Get a listing of folders (mailboxes) on the server
        """
        try:
            raw_list = self.conn.list_folders(directory, pattern)
            nice_list = []

            for mailbox in raw_list:
                flags = []
                for flag in mailbox[0]:
                    flags.append(flag.decode('utf-8'))

                nice_list.append({'name': mailbox[2], 'flags': flags, 'delimiter': mailbox[1].decode("utf-8")})
            return self.Retval(True, nice_list)
        except IMAPClient.Error as e:
            return self.process_error(e)

    def select_mailbox(self, mailbox):
        """
        Select a mailbox to work on
        """
        self.logger.debug('Switching to mailbox %s', mailbox)
        try:
            result = self.conn.select_folder(mailbox)
            response = {}
            for key, value in result.items():
                unicode_key = Helper().byte_to_str(key)
                if unicode_key == 'FLAGS':
                    flags = []
                    for flag in value:
                        flags.append(Helper().byte_to_str(flag))
                    response[unicode_key] = tuple(flags)
                else:
                    response[unicode_key] = value
            return self.Retval(True, response)
        except IMAPClient.Error as e:
            return self.process_error(e)

    def add_mail(self, mailbox, message, flags=(), msg_time=None):
        """
        Add/append a mail to a mailbox
        """
        self.logger.debug('Adding a mail into mailbox %s', mailbox)
        try:
            if not isinstance(message, Mail):
                message = Mail(logger=self.logger, mail_native=message)
            message_native = message.get_native()

            #self.conn.append(mailbox, message, flags, msg_time)
            self._append(mailbox, str(message_native), flags, msg_time)

            # According to rfc4315 we must not return the UID from the response, so we are fetching it ourselves
            uids = self.search_mails(mailbox=mailbox, criteria='HEADER Message-Id "{0}"'.format(message.get_header('Message-Id'))).data[0]

            return self.Retval(True, uids)
        except IMAPClient.Error as e:
            return self.process_error(e)

    @do_select_mailbox
    def search_mails(self, mailbox, criteria='ALL', autocreate_mailbox=False):
        """
        Search for mails in a mailbox
        """
        self.logger.debug('Searching for mails in mailbox %s and criteria=\'%s\'', mailbox, criteria)
        try:
            return self.Retval(True, list(self.conn.search(criteria=criteria)))
        except IMAPClient.Error as e:
            return self.process_error(e)

    @do_select_mailbox
    def fetch_mails(self, uids, mailbox, return_fields=None):
        """
        Retrieve mails from a mailbox
        """
        self.logger.debug('Fetching mails with uids %s', uids)

        return_raw = True
        if return_fields is None:
            return_raw = False
            return_fields = [b'RFC822']

        mails = {}
        try:
            for uid in uids:
                result = self.conn.fetch(uid, return_fields)

                if not result:
                    continue

                if return_raw:
                    mails[uid] = result[uid]
                else:
                    #mails[uid] = Mail(logger=self.logger, uid=uid, mail_native=email.message_from_bytes(result[uid][b'RFC822']))
                    mails[uid] = Mail(logger=self.logger, mail_native=email.message_from_bytes(result[uid][b'RFC822']))
            return self.Retval(True, mails)

        except IMAPClient.Error as e:
            return self.process_error(e)

    @do_select_mailbox
    def get_mailflags(self, uids, mailbox):
        """
        Retrieve flags from mails
        """
        try:
            result = self.conn.get_flags(uids)
            flags = {}

            for uid in uids:
                flags[uid] = []
                if uid not in result.keys():
                    self.logger.error('Failed to get flags for mail with uid=%s: %s', uid, result)
                    return self.Retval(False, None)
                for flag in result[uid]:
                    flags[uid].append(flag.decode('utf-8'))
            return self.Retval(True, flags)

        except IMAPClient.Error as e:
            return self.process_error(e)

    @do_select_mailbox
    def set_mailflags(self, uids, mailbox, flags=[]):
        """
        Set and retrieve flags from mails
        """
        if self.test:
            self.logger.info('Would have set mail flags on message uids "%s"', str(uids))
            return self.Retval(True, None)
        else:
            self.logger.debug('Setting flags=%s on mails uid=%s', flags, uids)
            try:
                result = self.conn.set_flags(uids, flags)

                _flags = {}
                for uid in uids:
                    _flags[uid] = []
                    if uid not in result.keys():
                        self.logger.error('Failed to set and get flags for mail with uid=%s: %s', uid, result)
                        return self.Retval(False, None)
                    for flag in result[uid]:
                        _flags[uid].append(flag.decode('utf-8'))
                return self.Retval(True, _flags)
            except IMAPClient.Error as e:
                return self.process_error(e)

    @do_select_mailbox
    def add_mailflags(self, uids, mailbox, flags=[]):
        """
        Add and retrieve flags from mails
        """
        if self.test:
            self.logger.info('Would have added mail flags on message uids "%s"', str(uids))
            return self.Retval(True, None)
        else:
            self.logger.debug('Adding flags=%s on mails uid=%s', flags, uids)
            try:
                result = self.conn.add_flags(uids, flags)

                _flags = {}
                for uid in uids:
                    _flags[uid] = []
                    if uid not in result.keys():
                        self.logger.error('Failed to add and get flags for mail with uid=%s: %s', uid, result)
                        return self.Retval(False, None)
                    for flag in result[uid]:
                        _flags[uid].append(flag.decode('utf-8'))
                return self.Retval(True, _flags)
            except IMAPClient.Error as e:
                return self.process_error(e)

    @do_select_mailbox
    def move_mail(self, message_ids, source, destination, delete_old=True, expunge=True, add_flags=None, set_flags=None):
        """
        Move a mail from a mailbox to another
        """
        return self.copy_mails(message_ids=message_ids,
                               source=source,
                               destination=destination,
                               delete_old=delete_old,
                               expunge=expunge,
                               add_flags=add_flags,
                               set_flags=set_flags)

    @do_select_mailbox
    def copy_mails(self, source, destination, message_ids=None, delete_old=False, expunge=False, add_flags=None, set_flags=None):
        """
        Copies one or more mails from a mailbox into another
        """
        if self.test:
            if delete_old:
                self.logger.info('Would have moved mail Message-Ids="%s" from "%s" to "%s", skipping because of beeing in testmode',
                                 message_ids, source, destination)
            else:
                self.logger.info('Would have copied mails with Message-Ids="%s" from "%s" to "%s", skipping because of beeing in testmode',
                                 message_ids, source, destination)
            return self.Retval(True, None)
        else:
            try:
                if delete_old:
                    self.logger.debug('Moving mail Message-Ids="%s" from "%s" to "%s"', message_ids, source, destination)
                else:
                    self.logger.debug('Copying mail Message-Ids="%s" from "%s" to "%s"', message_ids, source, destination)

                #if message_ids is None:
                #    message_ids = []
                #    result = self.fetch_mails(uids=uids, mailbox=source)
                #    if not result.code:
                #        self.logger.error('Failed to determine Message-Id by uids for mail with uids "%s"', uids)
                #        return result
                #    message_ids.append(result.data.keys())

                if not self.mailbox_exists(destination).data:
                    self.logger.info('Destination mailbox %s doesn\'t exist, creating it for you', destination)

                    result = self.create_mailbox(mailbox=destination)
                    if not result.code:
                        self.logger.error('Failed to create the mailbox %s: %s', source, result.data)  # pragma: no cover
                        return result  # pragma: no cover

                uids = []
                for message_id in message_ids:
                    result = self.search_mails(mailbox=source, criteria='HEADER Message-Id "{0}"'.format(message_id))

                    if not result.code or len(result.data) == 0:
                        self.logger.error('Failed to determine uid by Message-Id for mail with Message-Id "%s"', message_id)
                        return self.Retval(False, result.data)
                    uids.append(result.data[0])

                result = self.select_mailbox(source)
                if not result.code:
                    return result  # pragma: no cover

                self.conn.copy(uids, destination)

                if delete_old:
                    result = self.delete_mails(uids=uids, mailbox=source)
                    if not result.code:
                        self.logger.error('Failed to remove old mail with Message-Id="%s"/uids="%s": %s', message_ids, uids,
                                          result.data)  # pragma: no cover
                        return result  # pragma: no cover

                    if expunge:  # TODO don't expunge by default
                        result = self.expunge(mailbox=source)
                        if not result.code:
                            self.logger.error('Failed to expunge on mailbox %s: %s', source, result.data)  # pragma: no cover
                            return result  # pragma: no cover

                dest_uids = []
                for message_id in message_ids:
                    result = self.search_mails(mailbox=destination, criteria='HEADER Message-Id "{0}"'.format(message_id))
                    if not result.code:
                        self.logger.error('Failed to determine uid by Message-Id for mail with Message-Id "%s"',
                                          message_id)  # pragma: no cover
                        return result  # pragma: no cover
                    dest_uids.append(result.data[0])

                if isinstance(set_flags, list):
                    self.set_mailflags(uids=dest_uids, mailbox=destination, flags=set_flags)
                if add_flags:
                    self.add_mailflags(uids=dest_uids, mailbox=destination, flags=add_flags)

                return self.Retval(True, dest_uids)

            except IMAPClient.Error as e:
                return self.process_error(e)

    def _append(self, folder, msg, flags=(), msg_time=None):  # TODO
        """
        FORKED FORM IMAPCLIENT
        """
        if msg_time:
            if not msg_time.tzinfo:  # pragma: no cover
                msg_time = msg_time.replace(tzinfo=FixedOffset.for_system())  # pragma: no cover

            time_val = '"{0}"'.format(msg_time.strftime("%d-%b-%Y %H:%M:%S %z"))
            time_val = imapclient.imapclient.to_unicode(time_val)
        else:
            time_val = None

        return self.conn._command_and_check('append', self.conn._normalise_folder(folder), imapclient.imapclient.seq_to_parenstr(flags),
                                            time_val, Helper.str_to_bytes(msg),
                                            unpack=True)

    @do_select_mailbox
    def expunge(self, mailbox):
        """
        Expunge mails form a mailbox
        """
        self.logger.debug('Expunge mails from mailbox %s', mailbox)
        try:
            return self.Retval(True, b'Expunge completed.' in self.conn.expunge())
        except IMAPClient.Error as e:  # pragma: no cover
            return self.process_error(e)  # pragma: no cover

    def create_mailbox(self, mailbox):
        """
        Create a mailbox
        """
        self.logger.debug('Creating mailbox %s', mailbox)
        try:
            return self.Retval(True, self.conn.create_folder(mailbox) == b'Create completed.')
        except IMAPClient.Error as e:
            return self.process_error(e)

    def mailbox_exists(self, mailbox):
        """
        Check whether a mailbox exists
        """
        try:
            return self.Retval(True, self.conn.folder_exists(mailbox))
        except IMAPClient.Error as e:  # pragma: no cover
            return self.process_error(e)  # pragma: no cover

    @do_select_mailbox
    def delete_mails(self, uids, mailbox):
        """
        Delete mails
        """
        self.logger.debug('Deleting mails with uid="%s"', uids)
        try:
            result = self.conn.delete_messages(uids)
            flags = {}

            for uid in uids:
                flags[uid] = []
                if uid not in result.keys():
                    self.logger.error('Failed to get flags for mail with uid=%s after deleting it: %s', uid, result)
                    return self.Retval(False, None)
                for flag in result[uid]:
                    flags[uid].append(flag.decode('utf-8'))
            return self.Retval(True, flags)
        except IMAPClient.Error as e:
            return self.process_error(e)
Esempio n. 43
0
class Miner:
    """create a new email miner instance that can be used to traverse mails"""

    imap: IMAPClient = None

    def __init__(self,
                 hostname: str,
                 username: str,
                 password: str,
                 port: int = imaplib.IMAP4_SSL_PORT,
                 use_ssl: bool = True,
                 verify: bool = True,
                 log_level: int = None):
        """
        Create a new instance of the miner.

        :param hostname: the hostname of the imap server to connect to
        :param username: the user to login as
        :param password:
        :param port: the port to connect to. (defaults to 993)
        :param use_ssl: whether to use SSL to connect (defaults to True)
        :param verify: whether to verify the SSL certificates (defaults to False)
        """

        if log_level is not None:
            logging.basicConfig(
                format='%(asctime)s - %(levelname)s: %(message)s',
                level=log_level)

        ssl_context = ssl.create_default_context()

        if not verify:
            # disable hostname check. certificate may not match hostname.
            ssl_context.check_hostname = False
            # disable certificate authority verification. certificate maybe issued by unknown CA
            ssl_context.verify_mode = ssl.CERT_NONE

        self.imap = IMAPClient(host=hostname,
                               port=port,
                               ssl=use_ssl,
                               ssl_context=ssl_context)
        self.imap.login(username, password)

    @contextlib.contextmanager
    def folder(self, folder_name: str, read_only: bool = True):
        """
        Switch to a specific folder.

        :param folder_name: name of the folder to switch to
        :param read_only: read-only mode will not mark emails as read even after retrieval
        :return:
        """
        try:
            yield self.imap.select_folder(folder_name, read_only)
        finally:
            self.imap.close_folder()

    @contextlib.contextmanager
    def inbox(self, read_only: bool = True):
        """
        Switch to the inbox folder.

        :param read_only: read-only mode will not mark emails as read even after retrieval
        :return:
        """
        try:
            yield self.imap.select_folder('inbox', read_only)
        finally:
            self.imap.close_folder()

    def mark_as_unread(self, message_ids: List[int]):
        """
        Mark the given message IDs as unread by removing the SEEN flag.

        :param message_ids:
        :return:
        """
        self.imap.remove_flags(message_ids, [SEEN])

    def mark_as_read(self, message_ids: List[int]):
        """
        Mark the given message IDs as read by adding the SEEN flag.

        :param message_ids:
        :return:
        """
        self.imap.add_flags(message_ids, [SEEN])

    def delete(self, message_ids: List[int]):
        """
        Delete the given message IDs

        :param message_ids:
        :return:
        """
        self.imap.delete_messages(message_ids, True)

    def archive(self, message_ids: List[int]):
        """
        Archive the given message IDs

        :param message_ids:
        :return:
        """
        self.imap.copy(message_ids, br'\Archive')
        self.delete(message_ids)

    def get_emails(self,
                   unread_only: bool = True,
                   with_body: bool = False,
                   keep_as_unread: bool = False,
                   in_memory: bool = True) -> List[Email]:
        """
        Get emails from the selected folder.

        :param keep_as_unread: keep any retrieved emails as unread in the mailbox.
        :param unread_only: choose only to retrieve unread mails
        :param with_body: read-only mode will not mark emails as read even after retrieval
        :param in_memory: store the parsed attachments in-memory as bytes or to a temp file locally
        :return:
        """
        ids = self.imap.search('(UNSEEN)' if unread_only else 'ALL')
        flags = ['ENVELOPE', 'FLAGS', 'UID', 'INTERNALDATE']

        if with_body:
            flags.append('BODY[]')

        response = self.imap.fetch(ids, flags)

        try:
            if keep_as_unread:
                self.mark_as_unread(ids)
            else:
                self.mark_as_read(ids)
        except Exception:
            # will throw an exception if folder in read-only mode. so ignore.
            pass

        return parse_emails(response, in_memory)

    def __enter__(self):
        """
        return the instance of the miner for use as a context manager.

        :return:
        """
        return self

    def __exit__(self, *args):
        """
        Close folder and logout on exit when used as a context manager.

        :param args:
        :return:
        """
        if self.imap is not None:
            try:
                self.imap.close_folder()
            except:
                pass
            self.imap.logout()
    )
    originalFromName = data[b"ENVELOPE"].from_[0].name
    if (
        originalFromName is None
    ):  # from_ is a tuple of Address objects that represent one or more addresses from the “From” header, or None if header does not exist.
        originalFromName = data[b"ENVELOPE"].from_[0].mailbox.decode("utf-8")
    else:
        originalFromName = originalFromName.decode("utf-8")

    encodedText = data[b"BODY[TEXT]"].decode()

    if fromAddress in MAILING_LIST_USERS or fromAddress in TOLERATED_ALTERNATE_ADDRESSES:
        sendToAllUsers(data[b"ENVELOPE"].subject.decode("utf-8"), encodedText, fromAddress, originalFromName)
    else:
        sendToAdmin(data[b"ENVELOPE"].subject, encodedText, fromAddress)
        logging.warning(
            "{} tried to sent to the list but is not authorized. Forwarded to admin instead".format(fromAddress)
        )
    allNewIds.append(msgid)  # save for later deletion

if len(allNewIds):
    logging.info("deleted {} messages".format(len(allNewIds)))

server.delete_messages(allNewIds)
server.expunge()
server.logout()  # quit imap
mailserver.quit()  # quit smtp

now = datetime.datetime.now()
print("Written to log. Last run was @ ", now.isoformat())
Esempio n. 45
0
def fetchEMail(credentials):
    """
    Fetch all emails and delete old messages and other messages
    """
    from imapclient import IMAPClient
    rgx = re.compile(
        r"(\d+) crowdin entries linted for ([a-z]{2}(-[a-zA-Z]{2})?)")

    server = IMAPClient(credentials["host"], use_uid=True, ssl=True)
    server.login(credentials["user"], credentials["password"])

    select_info = server.select_folder('INBOX')
    print('{0} messages in INBOX'.format(select_info[b'EXISTS']))
    #Fetch list of emails
    messages = server.search(['NOT', 'DELETED'])
    msgmap = collections.defaultdict(list)
    # Fetch, filter and parse messages
    response = server.fetch(messages, [
        'BODY.PEEK[HEADER.FIELDS (SUBJECT)]',
        'BODY.PEEK[HEADER.FIELDS (DATE)]', 'RFC822'
    ])
    for msgid, data in response.items():
        try:
            subject = data[b'BODY[HEADER.FIELDS (SUBJECT)]'].decode("utf-8")
        except KeyError:
            continue
        if subject.startswith("Subject: "):
            subject = subject[len("Subject: "):]
        subject = subject.strip()
        # Date
        date = data[b'BODY[HEADER.FIELDS (DATE)]'].decode("utf-8").strip()
        if date.startswith("Date: "):
            date = date[len("Date: "):]
        if date.endswith("(PST)"):
            date = date[:-len("(PST)")].strip()
        if date.endswith("(PDT)"):
            date = date[:-len("(PDT)")].strip()
        if date.endswith("(UTC)"):
            date = date[:-len("(UTC)")].strip()
        if date.endswith("(CEST)"):
            date = date[:-len("(CEST)")].strip()
        if date.endswith("(EST)"):
            date = date[:-len("(EST)")].strip()
        try:
            date = datetime.strptime(date, "%a, %d %b %Y %H:%M:%S %z")
        except ValueError:
            date = datetime.strptime(date, "%d %b %Y %H:%M:%S %z")
        #
        match = rgx.match(subject)
        if not match:  # Delete message
            print('   Deleting "{1}"'.format(msgid, subject))
            server.delete_messages(msgid)
        else:
            msgmap[match.group(2)].append(
                KALintMail(msgid, subject, date,
                           data[b"RFC822"].decode("utf-8")))
    # Filter duplicates and sort by date
    msgmap = valmap(
        lambda vs: sorted(unique(vs, key=operator.attrgetter("msgid")),
                          key=operator.attrgetter("date")), msgmap)
    # Delete old messages
    msgidsToDelete = set()
    for lang, values in msgmap.items():
        msgidsToDelete.update([v.msgid for v in values[:-1]])
    server.delete_messages(msgidsToDelete)
    print("Deleted {0} messages".format(len(msgidsToDelete)))
    # Remove old messages from msgmap (keep only latest)
    return valmap(operator.itemgetter(-1), msgmap)
Esempio n. 46
0
class gmailPy(object):
    def __init__(self):
        self.IMAP_SERVER = 'imap.gmail.com'
        self.ssl = True
        self.myIMAPc = None
        self.response = None
        self.folders = []

    def login(self, username, password):
        self.myIMAPc = IMAPClient(self.IMAP_SERVER, ssl=self.ssl)
        self.myIMAPc.login(username, password)

    # Returns a list of all the folders for a particular account
    def get_folders(self):
        self.response = self.myIMAPc.list_folders()
        for item in self.response:
            self.folders.append(item[2].strip('u'))
        return self.folders

    # Returns the total number of messages in a folder
    def get_mail_count(self, folder='Inbox'):
        self.response = self.myIMAPc.select_folder(folder, True)
        return self.response['EXISTS']

    # Method to delete messages based on their size
    def delete_bigmail(self, folder='Inbox'):
        self.myIMAPc.select_folder(folder, False)
        # Gets all the message ids of the messages which are not deleted in the folder
        messages = self.myIMAPc.search(['NOT DELETED'])
        print "%d messages that aren't deleted" % len(messages)
        if len(messages) > 0:
            print "You can exit by entering 0 or pressing CTRL+C \n"
        else: print "There are no messages in the folder"
        # Gets the message sizes for all the message ids returned in previous step
        # Note: Just sends one request for all message ids with a return time < 10 ms
        self.response = self.myIMAPc.fetch(messages, ['RFC822.SIZE'])
        # Sorts the dictionary returned by fetch by size in descending order
        sorted_response = sorted(self.response.iteritems(), key=operator.itemgetter(1), reverse=True)
        count = 1
        try:
            for item in sorted_response:
                # Gets the biggest message including headers, body, etc.
                big_message = self.myIMAPc.fetch(item[0], ['RFC822'])
                for msgid, data in big_message.iteritems():
                    msg_string = data['RFC822']
                    # Parses the message string using email library
                    msg = email.message_from_string(msg_string)
                    val = dict(self.response[msgid])['RFC822.SIZE']
                    print 'ID %d: From: %s Date: %s' % (msgid, msg['From'], msg['date'])
                    print 'To: %s' % (msg['To'])
                    print 'Subject: %s' % (msg['Subject'])
                    print 'Size: %d bytes \n' % (val)
                    user_del = raw_input("Do you want to delete this message?(Y/N): ")
                    if user_del == 'Y':
                        self.delete_message(msgid)
                        if count == len(sorted_response):
                            print "There are no more messages"
                        else:
                            print "\nMoving on to the next biggest message >>> \n"
                    elif user_del == '0':
                        print "Program exiting"
                        sys.exit()
                    else:
                        if count == len(sorted_response):
                            print "There are no more messages"
                        else:
                            print "\nMoving on to the next biggest message >>> \n"
                    count += 1
        except KeyboardInterrupt:
            print "Program exiting"
            sys.exit()

    # Method to delete messages based on their size with a search criteria
    def delete_bigmail_search(self, folder='Inbox', command='', criteria=''):
        self.myIMAPc.select_folder(folder, False)
        # Gets all the message ids from the server based on the search criteria
        messages = self.myIMAPc.search('%s "%s"' % (command, criteria))
        print "%d messages that match --> %s: %s" % (len(messages), command, criteria)
        if len(messages) > 0:
            print "You can exit by entering 0 or pressing CTRL+C \n"
        else: print "There are no messages in that matched your search criteria"
        # Gets the message sizes for all the message ids returned in previous step
        # Note: Just sends one request for all message ids with a return time < 10 ms
        self.response = self.myIMAPc.fetch(messages, ['RFC822.SIZE'])
        # Sorts the messages in decending order of their sizes
        sorted_response = sorted(self.response.iteritems(), key=operator.itemgetter(1), reverse=True)
        count = 1
        try:
            for item in sorted_response:
                # Gets the entire content for the biggest message identified
                big_message = self.myIMAPc.fetch(item[0], ['RFC822'])
                for msgid, data in big_message.iteritems():
                    msg_string = data['RFC822']
                    msg = email.message_from_string(msg_string)
                    val = dict(self.response[msgid])['RFC822.SIZE']
                    print 'ID %d: From: %s Date: %s' % (msgid, msg['From'], msg['date'])
                    print 'To: %s' % (msg['To'])
                    print 'Subject: %s' % (msg['Subject'])
                    print 'Size: %d bytes \n' % (val)
                    user_del = raw_input("Do you want to delete this message?(Y/N): ")
                    if user_del == 'Y':
                        self.delete_message(msgid)
                        if count == len(sorted_response):
                            print "There are no more messages"
                        else:
                            print "\nMoving on to the next biggest message >>> \n"
                    elif user_del == '0':
                        print "Program exiting"
                        sys.exit()
                    else:
                        if count == len(sorted_response):
                            print "There are no more messages"
                        else:
                            print "\nMoving on to the next biggest message >>> \n"
                    count += 1

        except KeyboardInterrupt:
            print "Program exiting"
            sys.exit()

    # Deletes a message in the current folder based on msg id
    def delete_message(self, id):
        try:
            self.myIMAPc.delete_messages([id])
            self.myIMAPc.expunge()
            print "Message deleted"
        except IMAPClient.Error as err:
            print "Message deletion failed"
            print err

    # Renames a folder
    def rename_folder(self, oldfolder, newfolder):
        try:
            self.myIMAPc.rename_folder(oldfolder, newfolder)
            print "Folder %s renamed to %s" % (oldfolder, newfolder)
        except IMAPClient.Error as err:
            print "Folder renaming failed"
            print err

    # Creates a new folder
    def create_folder(self, folder):
        try:
            self.myIMAPc.create_folder(folder)
            print "New folder %s created" % folder
        except IMAPClient.Error as err:
            print "Folder creation failed"
            print err

    # Deletes a folder
    def delete_folder(self, folder):
        try:
            self.myIMAPc.delete_folder(folder)
            print "Folder %s deleted" % folder
        except IMAPClient.Error as err:
            print "Folder deletion failed"
            print err

    # Creates a new folder and copies the content from the two folders that need to be merged
    # Then deletes the old folders
    def merge_folders(self, merged_folder, folder_1, folder_2):
        try:
            self.create_folder(merged_folder)
            # Selects the folder with read/write permission
            self.myIMAPc.select_folder(folder_1, True)
            messages = self.myIMAPc.search(['NOT DELETED'])
            print "Moving %d messages from %s to %s" % (len(messages), folder_1, merged_folder)
            self.myIMAPc.copy(messages, merged_folder)
            self.myIMAPc.select_folder(folder_2, True)
            messages = self.myIMAPc.search(['NOT DELETED'])
            print "Moving %d messages from %s to %s" % (len(messages), folder_2, merged_folder)
            self.myIMAPc.copy(messages, merged_folder)
            print "Deleting %s and %s..." % (folder_1, folder_2)
            self.delete_folder(folder_1)
            self.delete_folder(folder_2)
            print "Merge folder operation succeeded"
        except IMAPClient.Error as err:
            print "Merge operation failed"
            print err

    def logout(self):
        self.myIMAPc.logout()