Пример #1
0
def test_send_mail(loop, fake_account, msg_test, settings):

    loop.run_until_complete(storage.start())

    from_addr = mailutils.parse_email("*****@*****.**")
    to_addrs = [mailutils.parse_email("*****@*****.**")]

    # First with bad recipient
    result = loop.run_until_complete(
        smtp.send_mail(fake_account, msg_test, from_addr, to_addrs))

    print(result)

    assert result["delivery_status"] == {
        "*****@*****.**": {
            "reason": "SMTP_ERROR",
            "smtp_info": "(554, b'5.5.1 Error: no inbox for this email')",
            "status": "ERROR",
        }
    }

    # Then good recipient
    to_addrs = [mailutils.parse_email("*****@*****.**")]

    result = loop.run_until_complete(
        smtp.send_mail(fake_account, msg_test, from_addr, to_addrs))

    print(result)

    assert result["delivery_status"] == {
        "*****@*****.**": {
            "status": "DELIVERED",
            "smtp_info": ("250", "Delivered"),
        }
    }
Пример #2
0
    async def sendmail(request, user_id, account):
        """ Send an email """

        if account.name != user_id:
            raise Forbidden("You can't consult another person account.")

        data = request.json

        from_addr = mailutils.parse_email(account.address)
        all_addrs = [
            mailutils.parse_email(a["address"]) for a in data["recipients"]
        ]
        tos = [
            mailutils.parse_email(a["address"]) for a in data["recipients"]
            if a["type"] == "to"
        ]
        ccs = [
            mailutils.parse_email(a["address"]) for a in data["recipients"]
            if a["type"] == "cc"
        ]

        attachments = data.get("attachments", [])

        msg = mailutils.make_msg(data["subject"], data["content"], from_addr,
                                 tos, ccs, attachments)

        result = await send_mail(account, msg, from_addr, all_addrs)

        return json(result)
Пример #3
0
    async def sendmail(request, account):
        data = request.json

        mail_sender = MailSender()

        from_addr = mailutils.parse_email(account.address)
        all_addrs = [mailutils.parse_email(a['address']) for a in data['recipients']]
        tos = [mailutils.parse_email(a['address']) for a in data['recipients'] if a['type'] == 'to']
        ccs = [mailutils.parse_email(a['address']) for a in data['recipients'] if a['type'] == 'cc']

        attachments = data.get('attachments', [])

        msg = mailutils.make_msg(data['subject'], data['content'], from_addr, tos, ccs, attachments)

        # First we store it
        saved_msg = await storage.store_msg(
            msg,
            account=account,
            from_addr=from_addr,
            to_addrs=all_addrs,
            incoming=False
        )

        # Then we send it
        delivery_status = await mail_sender.send(
            msg,
            from_addr=from_addr.addr_spec,
            to_addrs=[a.addr_spec for a in all_addrs]
        )

        # TODO update delivery status in store

        # Finally we return it
        return json(saved_msg)
Пример #4
0
def test_resend_mail(loop, fake_account, msg_test, settings):

    loop.run_until_complete(storage.start())

    from_addr = mailutils.parse_email("*****@*****.**")

    to_addrs = [
        mailutils.parse_email("*****@*****.**"),
        mailutils.parse_email("*****@*****.**"),
    ]

    with mock.patch("byemail.smtp.MsgSender._relay_to") as smtp_send:
        f = asyncio.Future(loop=loop)
        f.set_result({
            "*****@*****.**": ("250", "Delivered"),
            "*****@*****.**": ("534", "Fail for any reason"),
        })
        smtp_send.return_value = f

        mail_to_resend = loop.run_until_complete(
            smtp.send_mail(fake_account, msg_test, from_addr, to_addrs))

    assert mail_to_resend["delivery_status"] == {
        "*****@*****.**": {
            "status": "DELIVERED",
            "smtp_info": ("250", "Delivered"),
        },
        "*****@*****.**": {
            "status": "ERROR",
            "reason": "SMTP_ERROR",
            "smtp_info": ("534", "Fail for any reason"),
        },
    }

    with mock.patch("byemail.smtp.MsgSender._relay_to") as smtp_send:
        f = asyncio.Future(loop=loop)
        f.set_result({})
        smtp_send.return_value = f

        mail_to_resend = loop.run_until_complete(
            smtp.resend_mail(fake_account, mail_to_resend, [to_addrs[1]]))

    # Does the delivery status update ?
    assert mail_to_resend["delivery_status"] == {
        "*****@*****.**": {
            "status": "DELIVERED",
            "smtp_info": ("250", "Delivered"),
        },
        "*****@*****.**": {
            "status": "DELIVERED",
            "smtp_info": ("250", "Delivered")
        },
    }
Пример #5
0
def dnsconfig():
    """ Show configuration to apply to your DNS """
    context = {}

    print("# This is the guessed configuration for your domain.")
    print("# Remember you should execute this command on the server where")
    print("# you start byemail.")

    for account in settings.ACCOUNTS:
        result = []
        context["externalip"] = (
            request.urlopen("https://api.ipify.org/").read().decode("utf8"))
        context["address_domain"] = mailutils.parse_email(
            account["address"]).domain
        context["dkim_selector"] = settings.DKIM_CONFIG["selector"]
        context["dkim_domain"] = settings.DKIM_CONFIG["domain"]
        """with open(settings.DKIM_CONFIG['public_key']) as key:
            context['publickey'] = key.read().replace('\n', '')\
                .replace('-----BEGIN PUBLIC KEY-----', '')\
                .replace('-----END PUBLIC KEY-----', '')"""

        result.append(MX_TPL.format(**context))
        result.append(SPF_TPL.format(**context))
        # result.append(DKIM_TPL.format(**context))
        result.append(DMARC_TPL.format(**context))

        print(
            f"\n# For account {account['name']}, domain {context['address_domain']}\n"
        )
        print("\n".join(result))

    print()
Пример #6
0
def dnsconfig():
    context = {}

    print("# This is the guessed configuration for your domain.")
    print("# Remember you should execute this command on the server where")
    print("# you start byemail.")

    for account in settings.ACCOUNTS:
        result = []
        context['externalip'] = request.urlopen(
            'https://api.ipify.org/').read().decode('utf8')
        context['address_domain'] = mailutils.parse_email(
            account['address']).domain
        context['dkim_selector'] = settings.DKIM_CONFIG['selector']
        context['dkim_domain'] = settings.DKIM_CONFIG['domain']

        with open(settings.DKIM_CONFIG['public_key']) as key:
            context['publickey'] = key.read().replace('\n', '')\
                .replace('-----BEGIN PUBLIC KEY-----', '')\
                .replace('-----END PUBLIC KEY-----', '')

        result.append(MX_TPL.format(**context))
        result.append(SPF_TPL.format(**context))
        result.append(DKIM_TPL.format(**context))
        result.append(DMARC_TPL.format(**context))

        print("\n--- For account {name}, domain {dkim_domain}\n".format(
            **account, **context))
        print('\n'.join(result))
        print("\n---")
Пример #7
0
async def main():
    settings.init_settings()
    await storage.storage.start()
    fake = Faker()

    for account_name, account in account_manager.accounts.items():
        from_addr = mailutils.parse_email(account.address)
        print(f"Generate messages for {from_addr}...")

        for _ in range(randint(3, 5)):
            to_addr = mailutils.parse_email(fake.safe_email())
            for _ in range(randint(3, 5)):
                # First message
                subject = fake.sentence(nb_words=5, variable_nb_words=True)
                msg = mailutils.make_msg(subject=subject,
                                         content=fake.text(max_nb_chars=200,
                                                           ext_word_list=None),
                                         from_addr=from_addr,
                                         tos=[to_addr],
                                         ccs=None,
                                         attachments=None)
                msg_to_store = await mailutils.extract_data_from_msg(msg)
                saved_msg = await storage.storage.store_msg(
                    msg_to_store,
                    account=account,
                    from_addr=from_addr,
                    to_addrs=[to_addr],
                    incoming=False)

                # response
                msg = mailutils.make_msg(subject="Re: " + subject,
                                         content=fake.text(max_nb_chars=200,
                                                           ext_word_list=None),
                                         from_addr=to_addr,
                                         tos=[from_addr],
                                         ccs=None,
                                         attachments=None)

                msg_to_store = await mailutils.extract_data_from_msg(msg)
                saved_msg = await storage.storage.store_msg(
                    msg_to_store,
                    account=account,
                    from_addr=to_addr,
                    to_addrs=[from_addr],
                    incoming=True)

    await storage.storage.stop()
Пример #8
0
def _test_msg_signing():
    # Use https://www.mail-tester.com to test
    from_address = mailutils.parse_email(
        "Joe SixPack <*****@*****.**>")
    to_address = mailutils.parse_email("Suzie Q <*****@*****.**>")

    with mock.patch('byemail.mailutils.settings') as set_mock:
        set_mock.DKIM_CONFIG = {
            'private_key': os.path.join(DATADIR, 'example_private.pem'),
            'public_key': os.path.join(DATADIR, 'example_public.pem'),
            'selector': 'test',
            'domain': 'example.com',
            'headers': ['From', 'To', 'Subject', 'Date', 'Message-Id']
        }

        msg = mailutils.make_msg("Is dinner ready?",
                                 message_content,
                                 from_addr=from_address,
                                 tos=to_address)

        dkim_sign = mailutils.gen_dkim_sign(msg)

        #new_dkim = mailutils.gen_dkim_sign2(msg)
        #assert old_dkim == new_dkim, "DKIM differs"

        msg['DKIM-Signature'] = dkim_sign
        print(msg['DKIM-Signature'])

    with open(os.path.join(DATADIR, 'example_public.pem')) as key:
        publickey = key.read().replace('\n', '')\
            .replace('-----BEGIN PUBLIC KEY-----', '')\
            .replace('-----END PUBLIC KEY-----', '')

    def dnsfunc(*args):
        print("Called with ", *args)
        return DNS_DKIM_RESPONSE_TPL.format(publickey)

    assert dkim.verify(msg.as_string().encode(), dnsfunc=dnsfunc)
Пример #9
0
def test_make_msg(loop):
    """ Test message composition """
    from_address = mailutils.parse_email(
        "Joe SixPack <*****@*****.**>")
    to_address = mailutils.parse_email("Suzie Q <*****@*****.**>")

    with mock.patch('byemail.mailutils.settings') as set_mock:
        set_mock.DKIM_CONFIG = {
            'private_key': os.path.join(DATADIR, 'example_private.pem'),
            'public_key': os.path.join(DATADIR, 'example_public.pem'),
            'selector': 'test',
            'domain': 'example.com',
            'headers': ['From', 'To', 'Subject', 'Date', 'Message-Id']
        }

        msg = mailutils.make_msg("Is dinner ready?",
                                 message_content,
                                 from_addr=from_address,
                                 tos=to_address)

        print(msg)

        assert msg['From'] == str(from_address)
Пример #10
0
async def populate_with_test_data(storage):
    """ Populate database with test data for testing purpose """

    account = account_manager.get_account_for_address("*****@*****.**")
    print(account)

    for msg_src, from_addr in incoming_messages:
        msg = BytesParser(policy=policy.default).parsebytes(msg_src)
        recipients = [parse_email("Test <*****@*****.**>")]
        await storage.store_mail(account, msg, from_addr, recipients, incoming=True)

    for msg_src, recipients in outgoing_messages:
        from_addr = "*****@*****.**"
        msg = BytesParser(policy=policy.default).parsebytes(msg_src)
        await storage.store_mail(account, msg, from_addr, recipients, incoming=False)
Пример #11
0
    async def mail_resend(request, user_id, mail_id, account):
        """ Resend an email by uid for selected recipient"""

        if account.name != user_id:
            raise Forbidden("You can't consult another person account.")

        mail_to_resend = await storage.get_mail(mail_id)

        # Check permissions
        if mail_to_resend["account"] != account.name:
            raise Forbidden("You don't have permission to resend this mail.")

        data = request.json
        tos = [mailutils.parse_email(data["to"])]

        result = await resend_mail(account, mail_to_resend, tos)

        return json(result)
Пример #12
0
OUTGOING_1 = (
    b"""Content-Type: text/plain; charset="utf-8"\r
Content-Transfer-Encoding: 7bit\r
MIME-Version: 1.0\r
From: Test <*****@*****.**>\r
Subject: Second mail\r
Message-Id: <152060134529.22888.2561159661807344298@emiter>\r
To: Suzie <*****@*****.**>\r
Date: Fri, 09 Mar 2019 14:16:45 +0100\r
\r
Yes sure, why not.\r
\r
Test.\r
\r
""",
    [parse_email("Suzie <*****@*****.**>")],
)

incoming_messages = [INCOMING_1, INCOMING_2]
outgoing_messages = [OUTGOING_1]


async def populate_with_test_data(storage):
    """ Populate database with test data for testing purpose """

    account = account_manager.get_account_for_address("*****@*****.**")
    print(account)

    for msg_src, from_addr in incoming_messages:
        msg = BytesParser(policy=policy.default).parsebytes(msg_src)
        recipients = [parse_email("Test <*****@*****.**>")]