Exemplo n.º 1
0
def help(message, address=None, host=None):
    logger.info("Email to mailbot@%s" % HOST)

    try: 
        name, addr = parseaddr(message['from'].lower())
        imapAccount = ImapAccount.objects.get(email=addr)

        to_addr = message['From']
        from_addr = address + '@' + HOST
        subject = "YouPS Help"
        body = "Welcome to YouPS."

        ers = EmailRule.objects.filter(mode__imap_account=imapAccount, type='shortcut')
        if ers.exists():
            body += " Please find below a general help on managing your email shortcut.\n\n"
            for er in ers:
                body += "%s: <a href='mailto:%s'>%s</a>" % (er.name, er.get_forward_addr() +  "@" + host, er.get_forward_addr() +  "@" + host)
        else:
            body += "\nThere is no shortcut defined at the moment. Create your shortcut here: <a href='%s://%s'>%s://%s</a>" % (PROTOCOL, site.domain, PROTOCOL, site.domain)
    
        mail = MailResponse(From = from_addr, To = to_addr, Subject = subject, Body = body)
        relay.deliver(mail)
    except ImapAccount.DoesNotExist:
        subject = "YouPS registeration required"
        error_msg = 'Your email %s is not registered. Create your account here: %s://%s' % (addr, PROTOCOL, site.domain)
        mail = MailResponse(From = WEBSITE+"@" + host, To = addr, Subject = subject, Body = error_msg)
        relay.deliver(mail)
    except Exception as e:
        logger.exception(str(e))
Exemplo n.º 2
0
def test_craft_response_attachment():
    sample = MailResponse(To=list_name + "@librelist.com",
                          From=user_full_address,
                          Subject="Test message with attachments.",
                          Body="The body as one attachment.")

    sample.attach(filename="tests/model/mailinglist_tests.py",
                  content_type="text/plain",
                  disposition="attachment")

    sample['message-id'] = '123545666'

    im = sample.to_message()
    assert_equal(len([x for x in im.walk()]), 3)
    
    inmsg = MailRequest("fakepeer", None, None, str(sample))
    assert_equal(len(inmsg.all_parts()), 2)

    outmsg = craft_response(inmsg, list_name, list_name +
                                        "@librelist.com")
  
    om = outmsg.to_message()

    assert_equal(len([x for x in om.walk()]),
                 len([x for x in im.walk()]))

    assert 'message-id' in outmsg
Exemplo n.º 3
0
def test_craft_response_attachment():
    sample = MailResponse(To=list_name + "@librelist.com",
                          From=user_full_address,
                          Subject="Test message with attachments.",
                          Body="The body as one attachment.")

    sample.attach(filename="tests/model/mailinglist_tests.py",
                  content_type="text/plain",
                  disposition="attachment")

    sample['message-id'] = '123545666'

    im = sample.to_message()
    assert_equal(len([x for x in im.walk()]), 3)

    inmsg = MailRequest("fakepeer", None, None, str(sample))
    assert_equal(len(inmsg.all_parts()), 2)

    outmsg = craft_response(inmsg, list_name, list_name + "@librelist.com")

    om = outmsg.to_message()

    assert_equal(len([x for x in om.walk()]), len([x for x in im.walk()]))

    assert 'message-id' in outmsg
Exemplo n.º 4
0
def test_craft_response_no_attachment():
    sample = MailResponse(To=list_name + "@librelist.com",
                          From=user_full_address,
                          Subject="Test message with attachments.",
                          Body="The body as one attachment.")

    im = sample.to_message()
    assert_equal(len([x for x in im.walk()]), 1)
    assert_equal(im.get_payload(), sample.Body)

    inmsg = MailRequest("fakepeer", None, None, str(sample))
    assert_equal(len(inmsg.all_parts()), 0)
    assert_equal(inmsg.body(), sample.Body)

    outmsg = craft_response(inmsg, list_name, list_name + "@librelist.com")

    om = outmsg.to_message()
    assert_equal(om.get_payload(), sample.Body)

    assert_equal(len([x for x in om.walk()]), len([x for x in im.walk()]))
Exemplo n.º 5
0
def test_craft_response_no_attachment():
    sample = MailResponse(To=list_name + "@librelist.com",
                          From=user_full_address,
                          Subject="Test message with attachments.",
                          Body="The body as one attachment.")

    im = sample.to_message()
    assert_equal(len([x for x in im.walk()]), 1)
    assert_equal(im.get_payload(), sample.Body)
    
    inmsg = MailRequest("fakepeer", None, None, str(sample))
    assert_equal(len(inmsg.all_parts()), 0)
    assert_equal(inmsg.body(), sample.Body)

    outmsg = craft_response(inmsg, list_name, list_name +
                                        "@librelist.com")
  
    om = outmsg.to_message()
    assert_equal(om.get_payload(), sample.Body)

    assert_equal(len([x for x in om.walk()]),
                 len([x for x in im.walk()]))
Exemplo n.º 6
0
def test_archive_enqueue():
    msg = MailResponse(From=u'"p\xf6stal Zed" <*****@*****.**>',
                       To="*****@*****.**",
                       Subject="test message",
                       Body="This is a test.")

    archive.enqueue('test.list', msg)
    archived = delivered('zedshaw', to_queue=queue(queue_path))
    assert archived, "Didn't get archived."
    as_string = str(archived)

    assert '-AT-' in str(archived), "Didn't get obfuscated"
    assert '<' in as_string and '"' in as_string and '>' in as_string, "Unicode email screwed up."
Exemplo n.º 7
0
def test_post_message():
    for i in range(0, 3):
        add_subscriber(user_full_address, list_name)

    sample = MailResponse(To=list_name + "@librelist.com",
                          From=user_full_address,
                          Subject="Test post message.",
                          Body="I am telling you guys you are wrong.")

    sample['Message-Id'] = '12313123123123123'

    msg = MailRequest("fakepeer", sample['from'], sample['to'], str(sample))
    post_message(relay(port=8825), msg, list_name, "librelist.com")
Exemplo n.º 8
0
def craft_response(message, list_name, list_addr):
    response = MailResponse(To=list_addr,
                            From=message['from'],
                            Subject=message['subject'])

    msg_id = message['message-id']

    response.update({
        "Sender":
        list_addr,
        "Reply-To":
        list_addr,
        "List-Id":
        list_addr,
        "List-Unsubscribe":
        "<mailto:%[email protected]>" % list_name,
        "List-Archive":
        "<http://librelist.com/archives/%s/>" % list_name,
        "List-Post":
        "<mailto:%s>" % list_addr,
        "List-Help":
        "<http://librelist.com/help.html>",
        "List-Subscribe":
        "<mailto:%[email protected]>" % list_name,
        "Return-Path":
        list_addr,
        "Precedence":
        'list',
    })

    if 'date' in message:
        response['Date'] = message['date']

    if 'references' in message:
        response['References'] = message['References']
    elif msg_id:
        response['References'] = msg_id

    if msg_id:
        response['message-id'] = msg_id

        if 'in-reply-to' not in message:
            response["In-Reply-To"] = message['Message-Id']

    if message.all_parts():
        response.attach_all_parts(message)
    else:
        response.Body = message.body()

    return response
Exemplo n.º 9
0
def send_account_info(message, address=None, host=None):

    subj_string = message['Subject'].encode('utf-8').lower()
    activation_str = ("account activation on %s" % WEBSITE).lower()
    reset_str = ("password reset on %s" % WEBSITE).lower()

    logging.debug(message['Subject'])
    logging.debug(message['To'])
    logging.debug(message['From'])
    email_message = message_from_string(str(message))
    msg_text = get_body(email_message)
    logging.info(msg_text)

    if message['From'].encode('utf-8') == NO_REPLY and (activation_str in subj_string or reset_str in subj_string):
        
        email_message = email.message_from_string(str(message))
        msg_text = get_body(email_message)
        mail = MailResponse(From = NO_REPLY, To = message['To'], Subject = message['Subject'], Body = msg_text['plain'])
        relay.deliver(mail)
Exemplo n.º 10
0
def START(message, address=None, host=None):

    # Get the email addresses and the subject prefix/tag from an API URL.
    resp = requests.get("{0}{1}".format(config["url"], address))
    data = json.loads(resp.text)

    emails = data["emails"]
    prefix = data["tag"]

    if emails is None:
        raise SMTPError(550, "Unknown address")

    subject = message["Subject"]

    # Add the prefix if not already in the subject field
    if not prefix.lower() in subject.lower():
        new_subject = "{0} {1}".format(prefix, subject)
        del message["Subject"]
        message["Subject"] = new_subject

    if len(emails) > 0:
        if any(email is None for email in emails):
            # Send back to the sender
            emails = [message["From"]]
            message = MailResponse(
                To=message["From"],
                From="*****@*****.**",
                Subject="FAILED TO SEND: {0}".format(subject),
                Body="""
                Failed to send the email.

                Some recipients don't have email addresses defined.

                The email wasn't delivered to anyone.

                Please contact the administrator for help.
                """)
        relay.deliver(message, To=emails)
    else:
        logging.debug("No receivers, not relaying the email")
Exemplo n.º 11
0
def craft_response(message, list_name, list_addr):
    response = MailResponse(To=list_addr, 
                            From=message['from'],
                            Subject=message['subject'])

    msg_id = message['message-id']

    response.update({
        "Sender": list_addr, 
        "Reply-To": list_addr,
        "List-Id": list_addr,
        "List-Unsubscribe": "<mailto:%[email protected]>" % list_name,
        "List-Archive": "<http://librelist.com/archives/%s/>" % list_name,
        "List-Post": "<mailto:%s>" % list_addr,
        "List-Help": "<http://librelist.com/help.html>",
        "List-Subscribe": "<mailto:%[email protected]>" % list_name,
        "Return-Path": list_addr, 
        "Precedence": 'list',
    })

    if 'date' in message:
        response['Date'] = message['date']

    if 'references' in message:
        response['References'] = message['References']
    elif msg_id:
        response['References'] = msg_id

    if msg_id:
        response['message-id'] = msg_id

        if 'in-reply-to' not in message:
            response["In-Reply-To"] = message['Message-Id']

    if message.all_parts():
        response.attach_all_parts(message)
    else:
        response.Body = message.body()

    return response
Exemplo n.º 12
0
def START(message, address=None, host=None):
    if len(Message.objects.filter(message_id=get_message_id(message))) > 0:
        logging.debug("Ignoring message already uploaded: %s", get_message_id(message))
        return 

    human = find_sender(message)

    campaign = None
    campaign_id = message['X-Poisson-Magique-Campaign']
    if campaign_id is not None:
        try:
            campaign = Campaign.objects.get(pk=int(campaign_id))
        except Campaign.DoesNotExist:
            campaign = None
    if campaign is None:
        # re-do the searching for the campaign
        campaign = find_campaign_for_sender(human)

    # extract the text from the email

    # TODO: do something better here
    text = message.body()
    if text is None:
        text = "poissonmagique: no text extracted"

    # TODO: handle file attachments

    # write to the campaign logging queue
    campaign_queue = queue.Queue("run/campaign-%d" % ( campaign.id, ))
    key = campaign_queue.push(message)
    db_msg_id = queue_push(campaign_queue, message, key)
    message_id = db_msg_id.message_id

    # look for author's character, if any
    try:
        author_character = Character.objects.get(controller=human, campaign=campaign)
    except Character.DoesNotExist:
        author_character = None
    except Character.MultipleObjectsReturned:
        author_character = None

    # create base message
    # TODO: extract the time of the message for the 'when'
    db_msg = Message( message_id = message_id,
                      author_human = human,
                      author_character = author_character,
                      subject = message['Subject'],
                      campaign = campaign,
                      text = text,
                      when = datetime.now(),
                      game_time = campaign.game_time )
    db_msg.save()

    # recipients
    recipients = []
    if message['To'] is not None:
        recipients += message['To'].split(",")
    if message['cc'] is not None:
        recipients += message['Cc'].split(",")
    recipients_target = []
    for recipient in recipients:
        _, rcpt_address = parseaddr(recipient)
        target, character = find_recipient(rcpt_address, campaign, name='recipient')
        recipients_target.append( (target, character) )

        db_msg.receivers_human.add( target )
        if character is not None:
            db_msg.receivers_character.add( character )

    # check X-Must-Forward and forward appropriately
    if 'X-Must-Forward' in message and message['X-Must-Forward'] == 'True':
        # the sender is (human, character), the recipients are recipients_target

        if campaign.gm == human: # if sender is gm, send to all recipients right away
            from_gm = 'gm@%s' % (server_name,)
            for recipient in recipients_target:
                target = recipient[0]
                if target != human and target is not None:
                    # TODO: check if the GM is allowed to message this human
                    new_message = MailResponse(To=target.mail_address, From=from_gm, 
                                               Subject=message['Subject'],
                                               Body=message.body())
                    new_message.attach_all_parts(message)
                    new_message['X-Poisson-Magique'] = 'This is fictious email for a game, see http://%s for details.' % ( server_name,)
                    
                    relay.deliver(new_message)
        else:
            if human != campaign.gm and not campaign.gm.is_bouncing:
                # send to the actual GM, if it is not bouncing

                # use as From the UID
                new_from = 'poisson-%d@%s' % (human.user.id, server_name,)
                # find their character and use it as From, if any
                if author_character is not None:
                    new_from = "%s <%s>" % (author_character.name, author_character.mail_address)

                msg_id = message['Message-ID'][1:-1]
                new_message = MailResponse(To=campaign.gm.mail_address, From=new_from, 
                                           Subject=message['Subject'],
                                           Body="Original sender: %s.\nSee it online at http://%s/msg/%s.\n\n%s" % (
                        human.mail_address, web_server_name, msg_id, "" if message.base.parts else message.body()))
                new_message.attach_all_parts(message)
                new_message['X-Poisson-Magique'] = 'This is fictious email for a game, see http://%s for details.' % ( server_name,)

                relay.deliver(new_message)
Exemplo n.º 13
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.º 14
0
            new_message = create_response(arrived_message, addr,arrived_message["message-id"], body, host)
            relay.deliver(new_message)

    except ImapAccount.DoesNotExist:
        body_part = []
        body = {}
        body["text"] = '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)
        body["html"] = 'Your email %s is not registered or stopped due to an error. Write down your own email rule at <a href="%s://%s">%s://%s</a>' % (addr, PROTOCOL, site.domain, PROTOCOL, site.domain)
        
        mail = create_response(arrived_message, addr, arrived_message["message-id"], body, host)
        relay.deliver(mail)
    except Exception, e:
        logger.exception("Error while executing %s %s " % (e, traceback.format_exc()))
        subject = "[YoUPS] shortcuts Errors"
        mail = MailResponse(From = WEBSITE+"@" + host, To = arrived_message['From'], Subject = subject, Body = str(e))
        relay.deliver(mail)
    finally:
        if auth_res and auth_res['status']:
            # Log out after after conduct required action
            imap.logout()

def create_response(arrived_message, to, in_reply_to=None, body={"text":"", "body":""}, host="youps.csail.mit.edu"):
    new_message = MIMEMultipart('alternative')
    new_message["Subject"] = "Re: " + arrived_message["subject"]
    new_message["From"] = WEBSITE+"@" + host
    new_message["In-Reply-To"] = in_reply_to if in_reply_to else arrived_message["message-id"]
    new_message["To"] = to

    part1 = MIMEText(body["text"].encode('utf-8'), 'plain')
    part2 = MIMEText(body["html"].encode('utf-8'), 'html')