Exemplo n.º 1
0
def fetch_watch_message(user, email, watched_message):
    res = {'status': False, 'log': "", 'messages': {}}

    try:
        imapAccount = ImapAccount.objects.get(email=email)
        res['watch_status'] = True
    except ImapAccount.DoesNotExist:
        res['code'] = "Error during authentication. Please refresh"
        return

    try:
        imap = None

        auth_res = authenticate(imapAccount)
        if not auth_res['status']:
            raise ValueError(
                'Something went wrong during authentication. Refresh and try again!'
            )

        imap = auth_res['imap']  # noqa: F841 ignore unused
    except Exception as e:
        logger.exception("failed while logging into imap")
        res['code'] = "Fail to access your IMAP account"
        return

    try:
        if res['watch_status']:
            imapAccount.sync_paused = True
            mailbox = MailBox(imapAccount, imap, is_simulate=False)
            msgs = None
            cnt = 0
            while True:
                for folder in mailbox._list_selectable_folders():
                    response = imap.select_folder(folder.name)

                    highest_mod_seq = response.get('HIGHESTMODSEQ')
                    logger.debug(highest_mod_seq)

                    # this mailbox is using highest mod_seq and there is no update
                    if highest_mod_seq is not None and folder._highest_mod_seq <= 0:
                        continue

                    logger.info("refresh flags")

                    msgs = folder._refresh_flag_changes(highest_mod_seq)

                    if msgs:
                        for r in msgs:

                            # if this message is already caught, skip to next to find another new msgs
                            logger.debug(r.id)
                            logger.debug(watched_message)
                            if str(r.id) in watched_message:
                                continue
                            logger.info(r.base_message.subject)
                            message = Message(
                                r, imap_client=""
                            )  # since we are only extracting metadata, no need to use imap_client
                            res['message_schemaid'] = r.id
                            res['message'] = message._get_meta_data_friendly()
                            res['sender'] = message._get_from_friendly()

                            try:
                                message_arrival_time = dateutil.parser.parse(
                                    res["message"]["date"])
                                # if the message arrives today, send only hour and minute
                                if message_arrival_time.date(
                                ) == datetime.datetime.today().date():
                                    res["message"]["date"] = "%d:%02d" % (
                                        message_arrival_time.hour,
                                        message_arrival_time.minute)
                            except:
                                logger.exception(
                                    "parsing arrival date fail; skipping parsing"
                                )

                            res['context'] = {
                                'sender': res['sender']["name"],
                                "subject": res['message']['subject'],
                                "date": res["message"]["date"],
                                "message_id": res['message_schemaid']
                            }

                            # if there is update, send it to the client immediatly
                            if 'message' in res:
                                res['status'] = True
                                return res

                # r=requests.get(url, headers=headers)

                # if r.json()['deltas']:
                #     break
                # # logger.info("finding delta..")
                if cnt == 10:
                    break
                cnt = cnt + 1
                sleep(0.01)

            # for d in r.json()['deltas']:
            #     if d['object'] == "message" or d['object'] == "thread":
            #         logger.info(d['attributes']['subject'])
            #         res["log"] = d['attributes']['subject']

            # if bc and bc.code == ButtonChannel.OK:
            #     res['folder'] = bc.message.folder.name
            #     res['uid'] = bc.message.id

            #     message = Message(bc.message, imap_client="")   # since we are only extracting metadata, no need to use imap_client
            #     res['message'] = message._get_meta_data_friendly()
            #     res['sender'] = message._get_from_friendly()
            # else:
            #     # if something went wrong only return the log
            #     logger.info(bc.code)
            #     res["log"] = "%s - %s" % (bc.get_code_display(), bc.log)

        res['status'] = True

    except ButtonChannel.DoesNotExist:
        res['uid'] = 0
    except Exception as e:
        logger.exception(e)
        res['code'] = msg_code['UNKNOWN_ERROR']
    finally:
        logger.info("Finish watching cycle")
        imapAccount.sync_paused = False
        imap.logout()

    return res
Exemplo n.º 2
0
def START(message, address=None, host=None):

    logger.info("Email to mailbot@")

    arrived_message = message

    name, addr = parseaddr(arrived_message['from'].lower())
    site = Site.objects.get_current()
    auth_res = None
    # restart the db connection
    django.db.close_connection()
    
    try:
        addr = addr.strip()
        imapAccount = ImapAccount.objects.get(email=addr)

        er_to_execute = None
        ers = EmailRule.objects.filter(mode__imap_account=imapAccount, type='shortcut')
        for er in ers:
            if er.get_forward_addr().lower() == address.lower():
                er_to_execute = er
                break

        if not er_to_execute:
            body_part = []

            body = {}
            options = get_available_shortcut_link_text(imapAccount, site.domain) 
            body["text"] = "You email to %s@%s but this shortcut does not exist. \n\n %s \n\n Link to YouPS: %s://%s" % (address, host, options["text"], PROTOCOL, site.domain)
            body["html"] = "You email to %s@%s but this shortcut does not exist. <br><br> %s <br><br> Link to YouPS: <a href='%s://%s'>%s://%s</a>" % (address, host, options["html"], PROTOCOL, site.domain, PROTOCOL, site.domain)

            new_message = create_response(arrived_message, addr,arrived_message["message-id"], body, host)
            relay.deliver(new_message)
            return
            

        logging.debug("mailbot %s" % addr)
        auth_res = authenticate( imapAccount )
        if not auth_res['status']:
            raise ValueError('Something went wrong during authentication. Log in again at %s/editor' % host)
        imap = auth_res['imap']

        mailbox = MailBox(imapAccount, imap)

        # local shortcut
        if arrived_message["In-Reply-To"]:
            # Get the original message
            original_message_schema = MessageSchema.objects.filter(imap_account=imapAccount, base_message__message_id=arrived_message["In-Reply-To"])
            
            if original_message_schema.exists():
                original_message_schema = original_message_schema[0]

                imap.select_folder(original_message_schema.folder.name)           
                original_message = Message(original_message_schema, imap)
            else:
                # in case YouPS didn't register to DB yet, save the message to DB immediately 
                mail_found_at = ""
                original_message_id = -1
                for folder in mailbox._list_selectable_folders():
                    imap.select_folder(folder.name)
                    original_message_id = imap.search(["HEADER", "Message-ID", arrived_message["In-Reply-To"]])

                    # original_message

                    if original_message_id:
                        mail_found_at = folder
                        break
                
                if not mail_found_at:
                    raise ValueError("Email does not exist. The message is deleted or YouPS can't detect the message.")
                else: 
                    # Save this message immediately. so it can be ran when it is registered to the database  
                    try: 
                        logger.critical("%s %s" %(imapAccount.email, mail_found_at))
                        folder = mail_found_at

                        if original_message_id:
                            folder._save_new_messages(original_message_id[0], urgent=True)

                            original_message_schema = MessageSchema.objects.filter(imap_account=imapAccount, base_message__message_id=arrived_message["In-Reply-To"])
                            if not original_message_schema.exists():
                                raise
                            imap.select_folder(original_message_schema.folder.name)           
                            original_message = Message(original_message_schema, imap)

                    except FolderSchema.DoesNotExist, MessageSchema.DoesNotExist:
                        raise ValueError("Email does not exist. The message is deleted or YouPS can't detect the message.")

            entire_message = message_from_string(str(arrived_message))
            entire_body = get_body(entire_message)

            code_body = entire_body['plain'][:(-1)*len(original_message.content['text'])]
            gmail_header = "---------- Forwarded message ---------"
            if gmail_header in code_body:
                code_body = code_body.split(gmail_header)[0].strip()
            logging.debug(code_body)

            shortcuts = EmailRule.objects.filter(mode=imapAccount.current_mode, type="shortcut")
            if not imapAccount.current_mode or not shortcuts.exists():
                body = "Your YouPS hasn't turned on or don't have email shortcuts yet! Define your shortcuts here %s://%s" % (PROTOCOL, site.domain)

                mail = MailResponse(From = WEBSITE+"@" + host, To = imapAccount.email, Subject = "Re: " + original_message.subject, Body = body)
                relay.deliver(mail)

            else:
                
                res, body = run_shortcut(shortcuts, mailbox, original_message_schema, code_body)

                # Go to sent folder and delete the sent function from user  
                if imapAccount.is_gmail:
                    imap.select_folder('[Gmail]/Sent Mail')
                else:
                    import imapclient
                    sent = imap.find_special_folder(imapclient.SENT)
                    if sent is not None:
                        imap.select_folder(sent)
                this_message = imap.search(["HEADER", "In-Reply-To", original_message_schema.message_id])
                imap.delete_messages(this_message)

                # new_message.set_payload(content.encode('utf-8')) 
                if "text" in body and "html" in body:
                    body["text"] = "Your command: %s%sResult: %s" % (code_body, "\n\n", body["text"])
                    body["html"] = "Your command: %s%sResult: %s" % (code_body, "<br><br>", body["html"])
                else: 
                    body["text"] = "Your command:%s%sResult:%s" % (code_body, "\n\n", body["text"])

                new_message = create_response(arrived_message, addr, original_message_schema.message_id, body, host)

                try:
                    new_msg = {}
                    from_field = original_message._get_from_friendly()

                    to_field = original_message._get_to_friendly()

                    cc_field = original_message._get_cc_friendly()

                    new_msg["timestamp"] = str(datetime.now().strftime("%m/%d %H:%M:%S,%f"))
                    new_msg["type"] = "new_message"
                    new_msg["from_"] = from_field
                    new_msg["to"] = to_field
                    new_msg["cc"] = cc_field
                    new_msg["trigger"] = "shortcut"
                    new_msg["log"] = body["text"]
                    new_msg.update(original_message._get_meta_data_friendly())
                except Exception:
                    logger.critical("error adding logs")

                imap.append(original_message_schema.folder.name, str(new_message))
                # instead of sending email, just replace the forwarded email to arrive on the inbox quietly
        
        

        # global shortcut
        else:
Exemplo n.º 3
0
def mailbot(arrived_message, address=None, host=None):
    # no public groups to list on squadbox.
    if WEBSITE == 'squadbox' or WEBSITE == 'murmur':
        logging.debug("Ignored message to all@%s, no public groups to list" %
                      HOST)
        return

    else:
        logger.info("Email to mailbot@%s" % HOST)

        name, addr = parseaddr(arrived_message['from'].lower())
        site = None
        # restart the db connection
        django.db.close_connection()

        try:
            site = Site.objects.get_current()
            addr = addr.strip()
            imapAccount = ImapAccount.objects.get(email=addr)
            logging.debug("mailbot %s" % addr)
            auth_res = authenticate(imapAccount)
            if not auth_res['status']:
                raise ValueError(
                    'Something went wrong during authentication. Log in again at %s/editor'
                    % host)

            imap = auth_res['imap']

            mailbox = MailBox(imapAccount, imap)

            # Get the original message
            original_message_schema = MessageSchema.objects.filter(
                imap_account=imapAccount,
                message_id=arrived_message["In-Reply-To"])
            if original_message_schema.exists():
                original_message_schema = original_message_schema[0]

                imap.select_folder(original_message_schema.folder.name)
                original_message = Message(original_message_schema, imap)
            else:
                # in case YoUPS didn't register to DB yet, save the message to DB immediately
                mail_found_at = ""
                original_message_id = -1
                for folder in mailbox._list_selectable_folders():
                    imap.select_folder(folder.name)
                    original_message_id = imap.search([
                        "HEADER", "Message-ID", arrived_message["In-Reply-To"]
                    ])

                    # original_message

                    if original_message_id:
                        mail_found_at = folder
                        break

                if not mail_found_at:
                    raise ValueError(
                        "Email does not exist. The message is deleted or YoUPS can't detect the message."
                    )
                else:
                    # Save this message immediately. so it can be ran when it is registered to the database
                    try:
                        logger.critical("%s %s" %
                                        (imapAccount.email, mail_found_at))
                        folder = mail_found_at

                        if original_message_id:
                            folder._save_new_messages(original_message_id[0],
                                                      urgent=True)

                            original_message_schema = MessageSchema.objects.filter(
                                imap_account=imapAccount,
                                message_id=arrived_message["In-Reply-To"])
                            if not original_message_schema.exists():
                                raise
                            imap.select_folder(
                                original_message_schema.folder.name)
                            original_message = Message(original_message_schema,
                                                       imap)

                    except FolderSchema.DoesNotExist, MessageSchema.DoesNotExist:
                        raise ValueError(
                            "Email does not exist. The message is deleted or YoUPS can't detect the message."
                        )

            entire_message = message_from_string(str(arrived_message))
            entire_body = get_body(entire_message)

            code_body = entire_body['plain'][:(
                -1) * len(original_message.content['text'])]
            gmail_header = "---------- Forwarded message ---------"
            if gmail_header in code_body:
                code_body = code_body.split(gmail_header)[0].strip()
            logging.debug(code_body)

            shortcuts = EmailRule.objects.filter(mode=imapAccount.current_mode,
                                                 type="shortcut")
            if not imapAccount.current_mode or not shortcuts.exists():
                body = "Your YoUPS hasn't turned on or don't have email shortcuts yet! Define your shortcuts here %s://%s" % (
                    PROTOCOL, site.domain)

                mail = MailResponse(From=WEBSITE + "@" + host,
                                    To=imapAccount.email,
                                    Subject="Re: " + original_message.subject,
                                    Body=body)
                relay.deliver(mail)

            else:

                body = {"text": "", "html": ""}
                for shortcut in shortcuts:
                    res = interpret_bypass_queue(
                        mailbox,
                        None,
                        extra_info={
                            "msg-id": original_message_schema.id,
                            "code": shortcut.code,
                            "shortcut": code_body
                        })
                    logging.debug(res)

                    for key, value in res['appended_log'].iteritems():
                        if not value['error']:
                            body[
                                "text"] = 'Your mail shortcut is successfully applied! \n'
                            body[
                                "html"] = 'Your mail shortcut is successfully applied! <br>'
                        else:
                            body["text"] = 'Something went wrong! \n'
                            body["html"] = 'Something went wrong! <br>'

                        body["text"] = body["text"] + value['log']
                        body["html"] = body["html"] + value['log']

                    logger.debug(body)

                # Go to sent folder and delete the sent function from user
                if imapAccount.is_gmail:
                    imap.select_folder('[Gmail]/Sent Mail')
                else:
                    import imapclient
                    sent = imap.find_special_folder(imapclient.SENT)
                    if sent is not None:
                        imap.select_folder(sent)
                this_message = imap.search([
                    "HEADER", "In-Reply-To", original_message_schema.message_id
                ])
                imap.delete_messages(this_message)

                new_message = MIMEMultipart('alternative')
                new_message["Subject"] = "Re: " + arrived_message["subject"]
                new_message["From"] = WEBSITE + "@" + host
                new_message["In-Reply-To"] = original_message_schema.message_id

                try:
                    new_msg = {}
                    from_field = original_message._get_from_friendly()

                    to_field = original_message._get_to_friendly()

                    cc_field = original_message._get_cc_friendly()

                    new_msg["timestamp"] = str(
                        datetime.now().strftime("%m/%d %H:%M:%S,%f"))
                    new_msg["type"] = "new_message"
                    new_msg["from_"] = from_field
                    new_msg["to"] = to_field
                    new_msg["cc"] = cc_field
                    new_msg["trigger"] = "shortcut"
                    new_msg["log"] = body["text"]
                    new_msg.update(original_message._get_meta_data_friendly())
                    log_decoded = json.loads(imapAccount.execution_log) if len(
                        imapAccount.execution_log) else {}
                    log_decoded[new_msg["timestamp"]] = new_msg

                    imapAccount.execution_log = json.dumps(log_decoded)
                    imapAccount.save()
                except Exception:
                    logger.critical("error adding logs")

                # new_message.set_payload(content.encode('utf-8'))
                if "text" in body and "html" in body:
                    body["text"] = "Your command: %s%sResult: %s" % (
                        code_body, "\n\n", body["text"])
                    body["html"] = "Your command: %s%sResult: %s" % (
                        code_body, "<br><br>", body["html"])
                    part1 = MIMEText(body["text"].encode('utf-8'), 'plain')
                    part2 = MIMEText(body["html"].encode('utf-8'), 'html')
                    new_message.attach(part1)
                    new_message.attach(part2)
                else:
                    body["text"] = "Your command:%s%sResult:%s" % (
                        code_body, "\n\n", body["text"])
                    part1 = MIMEText(body["text"].encode('utf-8'), 'plain')
                    new_message.attach(part1)

                imap.append(original_message_schema.folder.name,
                            str(new_message))
                # instead of sending email, just replace the forwarded email to arrive on the inbox quietly

        except ImapAccount.DoesNotExist:
            subject = "YoUPS shortcuts Error"
            error_msg = 'Your email %s is not registered or stopped due to an error. Write down your own email rule at %s://%s' % (
                addr, PROTOCOL, site.domain)
            mail = MailResponse(From=WEBSITE + "@" + host,
                                To=arrived_message['From'],
                                Subject=subject,
                                Body=error_msg)
            relay.deliver(mail)