コード例 #1
0
ファイル: message.py プロジェクト: haystack/YouPS
    def forward(self, to=[], cc=[], bcc=[], content=""):
        to = format_email_address(to)
        cc = format_email_address(cc)
        bcc = format_email_address(bcc)

        new_message_wrapper = self._create_message_instance(
            "Fwd: " + self.subject, to, cc, bcc, content)

        if not self._is_simulate:
            if new_message_wrapper:
                from engine.models.mailbox import MailBox  # noqa: F401 ignore unused we use it for typing
                mailbox = MailBox(self._schema.imap_account, self._imap_client)
                mailbox._send_message( new_message_wrapper )
コード例 #2
0
ファイル: message.py プロジェクト: haystack/YouPS
    def reply(self, to=[], cc=[], bcc=[], content=""):
        # type: (t.Iterable[t.AnyStr], t.Iterable[t.AnyStr], t.Iterable[t.AnyStr], t.AnyStr) -> None
        """Reply to the sender of this message
        """
        if not self._is_simulate:
            to_addr = ""
            if isinstance(to, list):
                to_addr = to.append(self._schema.from_)
                to = format_email_address(to_addr)
            else:
                to = format_email_address([self._schema.from_, to])

            cc = format_email_address(cc)
            bcc = format_email_address(bcc)

            new_message_wrapper = self._create_message_instance(
                "Re: " + self.subject, to, cc, bcc, content)

            if new_message_wrapper:
                from engine.models.mailbox import MailBox  # noqa: F401 ignore unused we use it for typing
                mailbox = MailBox(self._schema.imap_account, self._imap_client)
                mailbox._send_message( new_message_wrapper )
コード例 #3
0
ファイル: youps.py プロジェクト: haystack/YouPS
def apply_button_rule(user, email, er_id, msg_schema_id, kargs):
    res = {'status': False}

    try:
        logger.info("here")
        imapAccount = ImapAccount.objects.get(email=email)
        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

        er = EmailRule.objects.get(id=er_id)
        #  read from DB and convert to the type accordingly
        for key, value in kargs.iteritems():
            er_arg = EmailRule_Args.objects.get(rule=er, name=key)

            # parse datetime
            if er_arg.type == "datetime":
                try:
                    kargs[key] = datetime.datetime.strptime(
                        value, '%Y-%m-%dT%H:%M')
                except Exception:
                    res['code'] = key
                    raise TypeError

        mailbox = MailBox(imapAccount, imap, is_simulate=False)
        res = interpret_bypass_queue(mailbox,
                                     extra_info={
                                         "msg-id": msg_schema_id,
                                         "code": er.code,
                                         "shortcut": kargs,
                                         "rule_name": er.name
                                     })
        logger.info(kargs)
        logger.info(er.code)
        logger.info(res)
        res['status'] = True

    except ImapAccount.DoesNotExist:
        res['code'] = "Error during deleting the mode. Please refresh the page."
    except MailbotMode.DoesNotExist:
        res['code'] = "Error during deleting the mode. Please refresh the page."
    except TypeError:
        res['code'] = "Datetime %s is in wrong format!" % res['code']
    except Exception as e:
        logger.exception(e)
        res['code'] = msg_code['UNKNOWN_ERROR']
    return res
コード例 #4
0
    def handle(self, *args, **options):

        # iterate over all the user accounts in the database
        imapAccounts = ImapAccount.objects.filter(is_initialized=False)

        for imapAccount in imapAccounts:
            if imapAccount.is_running:
                continue
            imapAccount.is_running = True
            imapAccount.save()

            res = {'status': False, 'imap_error': False}
            logger.info("run initial sync for email: %s" % imapAccount.email)

            # authenticate with the user's imap server
            auth_res = authenticate(imapAccount)
            # if authentication failed we can't run anything
            if not auth_res['status']:
                continue

            # get an imapclient which is authenticated
            imap = auth_res['imap']

            try:
                # create the mailbox
                mailbox = MailBox(imapAccount, imap)
                # sync the mailbox with imap
                mailbox._sync()
                logger.info("Mailbox sync done")
                # after sync, logout to prevent multi-connection issue
                imap.logout()
                logger.info(
                    "Mailbox logged out to prevent multi-connection issue")
                mailbox._run_user_code()
            except Exception:
                logger.exception("mailbox task running failed %s " %
                                 imapAccount.email)
                send_email("Your YoUPS account is ready!",
                           "no-reply@" + BASE_URL, '*****@*****.**',
                           "%s register inbox failed " % imapAccount.email)

                continue

            imapAccount.is_initialized = True
            imapAccount.is_running = False
            imapAccount.save()

            res['status'] = True
コード例 #5
0
ファイル: tasks.py プロジェクト: haystack/YouPS
def register_inbox():
    """Do the initial sync on an inbox.
    """


    lockFile = 'register_inbox2.lock'
    with open(lockFile, 'w') as f:
        have_lock = get_lock(f)
        if not have_lock:
            logger.info('Lock already taken %s' % lockFile)
            return

        for imapAccount in ImapAccount.objects.filter(is_initialized=False):
            try:
                logger.info('registering inbox: %s', imapAccount.email)

                while True:
                    try:
                        # authenticate with the user's imap server
                        auth_res = authenticate(imapAccount)
                        # if authentication failed we can't run anything
                        if not auth_res['status']:
                            # Stop doing loop
                            # TODO maybe we should email the user
                            logger.critical('register authentication failed for %s', imapAccount.email)
                            continue 

                        # get an imapclient which is authenticated
                        imap = auth_res['imap']  # type: IMAPClient


                        # create the mailbox
                        mailbox = MailBox(imapAccount, imap)
                        # TODO(lukemurray): remove this
                        mailbox._log_message_ids()
                        # sync the mailbox with imap
                        done = mailbox._sync()
                        if done:
                            break

                    # if we catch an EOF error we continue
                    except imaplib.IMAP4.abort:
                        logger.exception("Caught EOF error while syncing")
                        try:
                            imap.logout()
                        except Exception:
                            logger.exception("Failure while logging out due to EOF bug")
                        continue
                    # if we catch any other type of exception we abort to avoid infinite loop
                    except Exception:
                        logger.critical("Failure while initially syncing")
                        logger.exception("Failure while initially syncing")
                        raise

                logger.info("After sync, set up an exercise folder for the new user")
                try:
                        
                    imap.create_folder("_YouPS exercise")

                    msg1 = mailbox._create_message_wrapper("Welcome to YouPS!", imapAccount.email, content="This is the test email from YouPS", content_html="This is the test email from YouPS")
                    msg1["From"] = "*****@*****.**"
                    imap.append("_YouPS exercise", str(msg1))

                    msg1 = mailbox._create_message_wrapper("[Example email] Follow up", imapAccount.email + ", [email protected]", cc="*****@*****.**", content="Hello! I just wanted to follow up regarding our last meeting! Let me know how you think!", content_html="Hello! I just wanted to follow up regarding our last meeting! Let me know how you think!")
                    msg1["From"] = "*****@*****.**"
                    imap.append("_YouPS exercise", str(msg1))

                    msg1 = mailbox._create_message_wrapper("[Example email] Blah blah", imapAccount.email + ", [email protected]", cc="*****@*****.**", content="Howdy y'all!", content_html="Howdy y'all!")
                    msg1["From"] = "*****@*****.**"
                    imap.append("_YouPS exercise", str(msg1))

                except Exception as e:
                    logger.exception(e)


                logger.info("Mailbox sync done: %s" % (imapAccount.email))

                # after sync, logout to prevent multi-connection issue
                imap.logout()

                imapAccount.is_initialized = True
                imapAccount.save()

                site = Site.objects.get_current()
                # TODO(lukemurray): bring this back
                # send_email("Your YouPS account is ready!",
                #            "no-reply@" + BASE_URL,
                #            imapAccount.email,
                #            "Start writing your automation rule here! %s://%s" % (PROTOCOL, site.domain))

                # Create a default mode & email rule to demo

                logger.info(
                    'Register done for %s', imapAccount.email)
            except ImapAccount.DoesNotExist:
                imapAccount.is_initialized = False
                imapAccount.save()
                logger.exception(
                    "syncing fails Remove periodic tasks. imap_account not exist %s" % (imapAccount.email))

            except Exception as e:
                logger.exception(
                    "User inbox syncing fails %s. Stop syncing %s" % (imapAccount.email, e))
コード例 #6
0
ファイル: tasks.py プロジェクト: haystack/YouPS
def loop_sync_user_inbox():

    lockFile = 'loop_sync_user_inbox2.lock'
    with open(lockFile, 'w') as f:
        have_lock = get_lock(f)
        if not have_lock:
            logger.info('Lock already taken %s' % lockFile)
            return

        imapAccounts = ImapAccount.objects.filter(
            is_initialized=True)  # type: t.List[ImapAccount]
        for imapAccount in imapAccounts:
            # if imapAccount.email not in ["*****@*****.**", "*****@*****.**", "*****@*****.**"]:
            #     continue
            # refresh from database
            imapAccount = ImapAccount.objects.get(id=imapAccount.id)
            if not imapAccount.is_initialized:
                continue

            imapAccount_email = imapAccount.email

            try:
                logger.info('Start syncing %s ', imapAccount_email)

                # authenticate with the user's imap server
                auth_res = authenticate(imapAccount)
                # if authentication failed we can't run anything
                if not auth_res['status']:
                    # Stop doing loop
                    # TODO maybe we should email the user
                    logger.critical('authentication failed for %s' % imapAccount.email) 
                    continue

                # get an imapclient which is authenticated
                imap = auth_res['imap']

                # create the mailbox
                try:
                    mailbox = MailBox(imapAccount, imap)
                    # TODO(lukemurray): remove this

                    mailbox._log_message_ids()
                    # sync the mailbox with imap
                    mailbox._sync()
                    logger.info(mailbox.event_data_list)
                except Exception:
                    logger.exception("Mailbox sync failed")
                    # TODO maybe we should email the user
                    continue
                logger.debug("Mailbox sync done: %s" % (imapAccount_email))

                try:
                    # get scheduled tasks
                    email_rules = EmailRule.objects.filter(mode=imapAccount.current_mode, type__startswith='new-message-')  # type: t.List[EmailRule]
                    for email_rule in email_rules:
                        # Truncate millisec since mysql doesn't suport msec. 
                        now = timezone.now().replace(microsecond=0) + datetime.timedelta(seconds=1)

                        mailbox._manage_task(email_rule, now)

                        # mark timestamp to prevent running on certain message multiple times 
                        email_rule.executed_at = now + datetime.timedelta(seconds=1)
                        email_rule.save()
                        logger.info(mailbox.event_data_list)
                except Exception:
                    logger.exception("Mailbox managing task failed")
                    # TODO maybe we should email the user
                    continue
                logger.debug("Mailbox managing task done: %s" % (imapAccount_email))

                try:
                    # get deadline tasks
                    email_rules = EmailRule.objects.filter(mode=imapAccount.current_mode, type='deadline')  # type: t.List[EmailRule]
                    for email_rule in email_rules:
                        # Truncate millisec since mysql doesn't suport msec. 
                        now = timezone.now().replace(microsecond=0) + datetime.timedelta(seconds=1)
                        mailbox._get_due_messages(email_rule, now)

                        # mark timestamp to prevent running on certain message multiple times 
                        email_rule.executed_at = now + datetime.timedelta(seconds=1)
                        email_rule.save()
                        logger.info(mailbox.event_data_list)
                except Exception:
                    logger.exception("Mailbox managing task failed")
                    # TODO maybe we should email the user
                    continue
                try:
                    res = mailbox._run_user_code()
                    dump_execution_log(imapAccount, res['imap_log'])
                except Exception():
                    logger.exception("Mailbox run user code failed")

                

                # after sync, logout to prevent multi-connection issue
                imap.logout()

                logger.info(
                    'Sync done for %s', imapAccount_email)
            except ImapAccount.DoesNotExist:
                imapAccount.is_initialized = False
                imapAccount.save()
                logger.exception(
                    "syncing fails Remove periodic tasks. imap_account not exist %s" % (imapAccount_email))

            except Exception as e:
                logger.exception(
                    "User inbox syncing fails %s. Stop syncing %s" % (imapAccount_email, e))
コード例 #7
0
class Command(BaseCommand):
    args = ''
    help = 'Process email'

    # Auto-send messages to TEST_ACCOUNT_EMAIL and see the results match expected results by running multiple unit tests
    def handle(self, *args, **options):
        if len(args) == 0:
            print("option: send-test|run-test")
            print(
                "You should run `send-test` at least once prior to `run-test`")
            return

        test_emails = [
            {
                'subject':
                'test email %s ' %
                str(datetime.datetime.now().strftime("%m/%d %H:%M:%S,%f")),
                'from_addr':
                TEST_ACCOUNT_EMAIL,
                'to':
                "*****@*****.**",
                'cc':
                "",
                'bcc':
                "",
                'body_plain':
                'hello world',
                'body_html':
                'hi'
            },
            {
                'subject':
                'test email with emoji 🤷‍♀️ %s ' %
                str(datetime.datetime.now().strftime("%m/%d %H:%M:%S,%f")),
                'from_addr':
                TEST_ACCOUNT_EMAIL,
                'to':
                "[email protected], [email protected]",
                'cc':
                "[email protected], [email protected]",
                'bcc':
                "[email protected], [email protected], [email protected]",
                'body_plain':
                '😎',
                'body_html':
                '😎'
            },
        ]

        imapAccount = None
        imap = None

        # Auth to test email accountss
        try:
            imapAccount = ImapAccount.objects.get(email=TEST_ACCOUNT_EMAIL)
        except ImapAccount.DoesNotExist:
            login_imap(TEST_ACCOUNT_EMAIL,
                       TEST_ACCOUNT_PASSWORD,
                       'imap.gmail.com',
                       is_oauth=False)

            print(
                "Just created a YouPS account for a test account. It will take couple minutes to set up"
            )
            return

        try:
            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, e:
            print("failed logging into imap", str(e))
            return

        if args[0] == "send-test":
            mailbox = MailBox(imapAccount, imap, is_simulate=False)
            for i in range(len(test_emails)):
                test = test_emails[i]
                mailbox.send(subject="#%d " % i + test['subject'].decode('utf-8'), to=test['to'], cc=test['cc'], bcc=test['bcc'], \
                    body=test['body_plain'].decode('utf-8'), body_html=test['body_html'].decode('utf-8')) # TODO cc, bcc

            # index = 0
            # for t in test_emails:
            # #     # TODO send using django core
            # #     send_mail("#%d " % index + t['subject'].decode('utf-8'), t['body_plain'], TEST_ACCOUNT_EMAIL, [TEST_ACCOUNT_EMAIL])
            #     send_email("#%d " % index + t['subject'].decode('utf-8'), t['from_addr'], TEST_ACCOUNT_EMAIL, t['body_plain'].decode('utf-8'), t['body_html'].decode('utf-8'))
            #     index = index + 1

        elif args[0] == "run-test":
            test_cases = [
                [  # test cases for #0 email
                    {
                        'code': 'print (my_message.from_)',
                        'expected': TEST_ACCOUNT_EMAIL
                    },
                    {
                        'code':
                        'print("True" if "%s" == my_message.from_ else "") ' %
                        TEST_ACCOUNT_EMAIL,
                        'expected':
                        "True"
                    },
                    {
                        'code':
                        'print("True" if "test email " in my_message.subject else "") ',
                        'expected': 'True'
                    },
                ],
                [{
                    'code':
                    'print ("True" if "🤷‍♀️" in my_message.subject else "")',
                    'expected': 'True'
                }, {
                    'code':
                    'print ("True" if my_message.contains("😎") else "")',
                    'expected': 'True'
                }, {
                    'code': 'print ("*****@*****.**" in my_message.to)',
                    'expected': 'True'
                }, {
                    'code': 'print ("*****@*****.**" in my_message.cc)',
                    'expected': 'True'
                }, {
                    'code': 'print (len(my_message.cc) == 2)',
                    'expected': 'True'
                }, {
                    'code':
                    """my_message.add_flags("test")\n\tprint (my_message.has_flag("test"))""",
                    'expected': 'True'
                }, {
                    'code':
                    """my_message.remove_flags("test")\n\tprint (my_message.has_flag("test"))""",
                    'expected': 'False'
                }]
            ]

            # Run test
            try:
                folder_names = ["INBOX"]
                for msg_index in range(len(test_cases)):
                    for folder_name in folder_names:
                        # pick up recent messages
                        message = MessageSchema.objects.filter( \
                            imap_account=imapAccount, folder__name=folder_name, base_message__subject__startswith='#%d ' % msg_index).order_by("-base_message__date")

                        if not message.exists():
                            print(
                                "Unable to load the corresponding message #%d %s"
                                %
                                (msg_index, test_emails[msg_index]['subject']))
                            continue

                        message = message[0]
                        assert isinstance(message, MessageSchema)

                        mailbox = MailBox(imapAccount, imap, is_simulate=False)
                        for test_per_message_index in range(
                                len(test_cases[msg_index])):
                            imap_res = interpret_bypass_queue(mailbox, extra_info={'code': "def on_message(my_message):\n\t" + \
                                test_cases[msg_index][test_per_message_index]['code'].decode("utf-8", "replace"), 'msg-id': message.id})
                            # print(imap_res)

                            try:
                                # print(imap_res['appended_log'][message.id])
                                result = imap_res['appended_log'][
                                    message.id]['log'].rstrip("\n\r")
                                assert result == test_cases[msg_index][
                                    test_per_message_index]['expected']
                            except AssertionError:
                                print ("CASE #%d-%d %s (expected %s)" % (msg_index, test_per_message_index, \
                                    result, test_cases[msg_index][test_per_message_index]['expected']))
                                continue

                            print("SUCCESS #%d-%d %s" %
                                  (msg_index, test_per_message_index,
                                   message.base_message.subject))
            except Exception, e:
                print("failed while doing a user code run %s %s " %
                      (e, traceback.format_exc()))
            finally:
コード例 #8
0
ファイル: youps.py プロジェクト: asleepinthetrees/murmur
    except Exception, e:
        logger.exception("failed while logging into imap")
        res['code'] = "Fail to access your IMAP account"
        return

    try:
        res['messages'] = {}

        messages = MessageSchema.objects.filter(
            imap_account=imapAccount,
            folder_schema__name=folder_name).order_by("-date")[:N]
        imap.select_folder(folder_name)

        for message_schema in messages:

            imap_res = interpret(MailBox(imapAccount, imap),
                                 None,
                                 bypass_queue=True,
                                 is_simulate=True,
                                 extra_info={
                                     'code': code,
                                     'msg-id': message_schema.id
                                 })
            logger.info(imap_res)

            message = Message(message_schema, imap)

            from_field = None
            if message_schema.from_m:
                from_field = {
                    "name": message.from_.name,
コード例 #9
0
ファイル: tasks.py プロジェクト: soyapark/YouPS
def register_inbox():
    """Do the initial sync on an inbox.
    """

    lockFile = 'register_inbox.lock'
    with open(lockFile, 'w') as f:
        have_lock = get_lock(f)
        if not have_lock:
            logger.info('Lock already taken %s' % lockFile)
            return

        for imapAccount in ImapAccount.objects.filter(is_initialized=False):
            try:
                logger.info('registering inbox: %s', imapAccount.email)

                while True:
                    try:
                        # authenticate with the user's imap server
                        auth_res = authenticate(imapAccount)
                        # if authentication failed we can't run anything
                        if not auth_res['status']:
                            # Stop doing loop
                            # TODO maybe we should email the user
                            logger.critical(
                                'register authentication failed for %s',
                                imapAccount.email)
                            continue

                        # get an imapclient which is authenticated
                        imap = auth_res['imap']  # type: IMAPClient

                        # create the mailbox
                        mailbox = MailBox(imapAccount, imap)
                        # sync the mailbox with imap
                        done = mailbox._sync()
                        if done:
                            break

                    # if we catch an EOF error we continue
                    except imaplib.IMAP4.abort:
                        logger.exception("Caught EOF error while syncing")
                        try:
                            imap.logout()
                        except Exception:
                            logger.exception(
                                "Failure while logging out due to EOF bug")
                        continue
                    # if we catch any other type of exception we abort to avoid infinite loop
                    except Exception:
                        logger.critical("Failure while initially syncing")
                        logger.exception("Failure while initially syncing")
                        raise

                logger.info("Mailbox sync done: %s" % (imapAccount.email))

                # after sync, logout to prevent multi-connection issue
                imap.logout()

                imapAccount.is_initialized = True
                imapAccount.save()

                site = Site.objects.get_current()
                send_email(
                    "Your YoUPS account is ready!", "no-reply@" + BASE_URL,
                    imapAccount.email,
                    "Start writing your automation rule here! %s://%s" %
                    (PROTOCOL, site.domain))

                logger.info('Register done for %s', imapAccount.email)
            except ImapAccount.DoesNotExist:
                imapAccount.is_initialized = False
                imapAccount.save()
                logger.exception(
                    "syncing fails Remove periodic tasks. imap_account not exist %s"
                    % (imapAccount.email))

            except Exception as e:
                logger.exception(
                    "User inbox syncing fails %s. Stop syncing %s" %
                    (imapAccount.email, e))
コード例 #10
0
ファイル: youps.py プロジェクト: soyapark/YouPS
    except Exception, e:
        logger.exception("failed while logging into imap")
        res['code'] = "Fail to access your IMAP account"
        return

    try:
        res['messages'] = {}

        for folder_name in folder_names:
            messages = MessageSchema.objects.filter(
                imap_account=imapAccount,
                folder__name=folder_name).order_by("-base_message__date")[:N]

            for message_schema in messages:
                assert isinstance(message_schema, MessageSchema)
                mailbox = MailBox(imapAccount, imap, is_simulate=True)
                imap_res = interpret_bypass_queue(mailbox,
                                                  None,
                                                  extra_info={
                                                      'code': code,
                                                      'msg-id':
                                                      message_schema.id
                                                  })
                logger.debug(imap_res)

                message = Message(message_schema, imap)

                from_field = None
                if message.from_:
                    from_field = {
                        "name": message.from_.name,
コード例 #11
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:
コード例 #12
0
ファイル: youps.py プロジェクト: haystack/YouPS
def run_simulate_on_messages(user, email, folder_names, N=3, code=''):
    """This function is called to evaluate user's code on messages

        Args:
            user (Model.UserProfile)
            email (string): user's email address
            folder_name (string): name of a folder to extract messages 
            N (int): number of recent messages
            code (string): code to be simulated
    """
    res = {'status': False, 'imap_error': False, 'imap_log': ""}
    logger = logging.getLogger('youps')  # type: logging.Logger

    # this log is going to stdout but not going to the logging file
    # why are django settings not being picked up
    logger.info("user %s has requested simulation" % email)

    imapAccount = None
    imap = None

    try:
        imapAccount = ImapAccount.objects.get(email=email)
        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:
        res['messages'] = {}

        for folder_name in folder_names:
            messages = MessageSchema.objects.filter(
                imap_account=imapAccount,
                folder__name=folder_name).order_by("-base_message__date")[:N]

            for message_schema in messages:
                assert isinstance(message_schema, MessageSchema)
                mailbox = MailBox(imapAccount, imap, is_simulate=True)
                imap_res = interpret_bypass_queue(mailbox,
                                                  extra_info={
                                                      'code': code,
                                                      'msg-id':
                                                      message_schema.id
                                                  })
                logger.debug(imap_res)

                message = Message(message_schema, imap)

                from_field = None
                if message.from_:
                    from_field = {
                        "name": message.from_.name,
                        "email": message.from_.email,
                        "organization": message.from_.organization,
                        "geolocation": message.from_.geolocation
                    }

                to_field = [{
                    "name": tt.name,
                    "email": tt.email,
                    "organization": tt.organization,
                    "geolocation": tt.geolocation
                } for tt in message.to]

                cc_field = [{
                    "name": tt.name,
                    "email": tt.email,
                    "organization": tt.organization,
                    "geolocation": tt.geolocation
                } for tt in message.cc]

                # TODO attach activated line
                # This is to log for users
                new_msg = {
                    "timestamp":
                    str(datetime.datetime.now().strftime("%m/%d %H:%M:%S,%f")),
                    "type":
                    "new_message",
                    "folder":
                    message.folder.name,
                    "from_":
                    from_field,
                    "subject":
                    message.subject,
                    "to":
                    to_field,
                    "cc":
                    cc_field,
                    "flags":
                    [f.encode('utf8', 'replace') for f in message.flags],
                    "date":
                    str(message.date),
                    "deadline":
                    str(message.deadline),
                    "is_read":
                    message.is_read,
                    "is_deleted":
                    message.is_deleted,
                    "is_recent":
                    message.is_recent,
                    "log":
                    imap_res['appended_log'][message_schema.id]['log'],
                    "error":
                    imap_res['appended_log'][message_schema.id]['error']
                    if 'error' in imap_res['appended_log'][message_schema.id]
                    else False
                }

                res['messages'][message_schema.id] = new_msg

        res['status'] = True
    except ImapAccount.DoesNotExist:
        logger.exception("failed while doing a user code run")
        res['code'] = "Not logged into IMAP"
    except FolderSchema.DoesNotExist:
        logger.exception("failed while doing a user code run")
        logger.debug("Folder is not found, but it should exist!")
    except Exception as e:
        logger.exception("failed while doing a user code run %s %s " %
                         (e, traceback.format_exc()))
        res['code'] = msg_code['UNKNOWN_ERROR']
    finally:
        imap.logout()

    logging.debug(res)
    return res
コード例 #13
0
ファイル: youps.py プロジェクト: haystack/YouPS
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
コード例 #14
0
ファイル: main.py プロジェクト: soyapark/YouPS
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)