<commit_before># coding=utf-8
# Python 2 source containing unicode https://www.python.org/dev/peps/pep-0263/
"""
Tests for SMTP server rate limit feature.

<NAME> <<EMAIL>>
"""
import textwrap
import datetime
import time
import future.backports.email as email
import future.backports.email.parser  # pylint: disable=unused-import
import pytest
import click
import click.testing
from mailmerge import SendmailClient, MailmergeRateLimitError
from mailmerge.__main__ import main

try:
    from unittest import mock  # Python 3
except ImportError:
    import mock  # Python 2

# Python 2 pathlib support requires backport
try:
    from pathlib2 import Path
except ImportError:
    from pathlib import Path

# The sh library triggers lot of false no-member errors
# pylint: disable=no-member

# We're going to use mock_SMTP because it mimics the real SMTP library
# pylint: disable=invalid-name


@mock.patch('smtplib.SMTP')
def test_sendmail_ratelimit(mock_SMTP, tmp_path):
    """Verify SMTP library calls."""
    config_path = tmp_path/"server.conf"
    config_path.write_text(textwrap.dedent(u"""\
        [smtp_server]
        host = open-smtp.example.com
        port = 25
        ratelimit = 60
    """))
    sendmail_client = SendmailClient(
        config_path,
        dry_run=False,
    )
    message = email.message_from_string(u"""
        TO: <EMAIL>
        SUBJECT: Testing mailmerge
        FROM: <EMAIL>

        Hello world
    """)

    # First message
    sendmail_client.sendmail(
        sender="<EMAIL>",
        recipients=["<EMAIL>"],
        message=message,
    )
    smtp = mock_SMTP.return_value.__enter__.return_value
    assert smtp.sendmail.call_count == 1

    # Second message exceeds the rate limit, doesn't try to send a message
    with pytest.raises(MailmergeRateLimitError):
        sendmail_client.sendmail(
            sender="<EMAIL>",
            recipients=["<EMAIL>"],
            message=message,
        )
    assert smtp.sendmail.call_count == 1

    # Retry the second message after 1 s because the rate limit is 60 messages
    # per minute
    # FIXME a better way to do this is to mock datetime.datetime.now()
    time.sleep(1.1)
    sendmail_client.sendmail(
        sender="<EMAIL>",
        recipients=["<EMAIL>"],
        message=message,
    )
    assert smtp.sendmail.call_count == 2


@mock.patch('smtplib.SMTP')
def test_stdout_ratelimit(mock_SMTP, tmpdir):
    """Verify SMTP server ratelimit parameter."""
    # Simple template
    template_path = Path(tmpdir/"mailmerge_template.txt")
    template_path.write_text(textwrap.dedent(u"""\
        TO: {{email}}
        FROM: <EMAIL>

        Hello world
    """))

    # Simple database with two entries
    database_path = Path(tmpdir/"mailmerge_database.csv")
    database_path.write_text(textwrap.dedent(u"""\
        email
        <EMAIL>
        <EMAIL>
    """))

    # Simple unsecure server config
    config_path = Path(tmpdir/"mailmerge_server.conf")
    config_path.write_text(textwrap.dedent(u"""\
        [smtp_server]
        host = open-smtp.example.com
        port = 25
        ratelimit = 60
    """))

    # Run mailmerge
    before = datetime.datetime.now()
    with tmpdir.as_cwd():
        runner = click.testing.CliRunner(mix_stderr=False)
        result = runner.invoke(
            main, [
                "--no-limit",
                "--no-dry-run",
                "--output-format", "text",
            ]
        )
    after = datetime.datetime.now()
    assert after - before > datetime.timedelta(seconds=1)
    assert result.exit_code == 0
    assert result.stderr == ""
    assert ">>> message 1 sent" in result.stdout
    assert ">>> rate limit exceeded, waiting ..." in result.stdout
    assert ">>> message 2 sent" in result.stdout
<commit_msg>add another check<commit_after># coding=utf-8
# Python 2 source containing unicode https://www.python.org/dev/peps/pep-0263/
"""
Tests for SMTP server rate limit feature.

<NAME> <<EMAIL>>
"""
import textwrap
import datetime
import time
import future.backports.email as email
import future.backports.email.parser  # pylint: disable=unused-import
import pytest
import click
import click.testing
from mailmerge import SendmailClient, MailmergeRateLimitError
from mailmerge.__main__ import main

try:
    from unittest import mock  # Python 3
except ImportError:
    import mock  # Python 2

# Python 2 pathlib support requires backport
try:
    from pathlib2 import Path
except ImportError:
    from pathlib import Path

# The sh library triggers lot of false no-member errors
# pylint: disable=no-member

# We're going to use mock_SMTP because it mimics the real SMTP library
# pylint: disable=invalid-name


@mock.patch('smtplib.SMTP')
def test_sendmail_ratelimit(mock_SMTP, tmp_path):
    """Verify SMTP library calls."""
    config_path = tmp_path/"server.conf"
    config_path.write_text(textwrap.dedent(u"""\
        [smtp_server]
        host = open-smtp.example.com
        port = 25
        ratelimit = 60
    """))
    sendmail_client = SendmailClient(
        config_path,
        dry_run=False,
    )
    message = email.message_from_string(u"""
        TO: <EMAIL>
        SUBJECT: Testing mailmerge
        FROM: <EMAIL>

        Hello world
    """)

    # First message
    sendmail_client.sendmail(
        sender="<EMAIL>",
        recipients=["<EMAIL>"],
        message=message,
    )
    smtp = mock_SMTP.return_value.__enter__.return_value
    assert smtp.sendmail.call_count == 1

    # Second message exceeds the rate limit, doesn't try to send a message
    with pytest.raises(MailmergeRateLimitError):
        sendmail_client.sendmail(
            sender="<EMAIL>",
            recipients=["<EMAIL>"],
            message=message,
        )
    assert smtp.sendmail.call_count == 1

    # Retry the second message after 1 s because the rate limit is 60 messages
    # per minute
    # FIXME a better way to do this is to mock datetime.datetime.now()
    time.sleep(1.1)
    sendmail_client.sendmail(
        sender="<EMAIL>",
        recipients=["<EMAIL>"],
        message=message,
    )
    assert smtp.sendmail.call_count == 2


@mock.patch('smtplib.SMTP')
def test_stdout_ratelimit(mock_SMTP, tmpdir):
    """Verify SMTP server ratelimit parameter."""
    # Simple template
    template_path = Path(tmpdir/"mailmerge_template.txt")
    template_path.write_text(textwrap.dedent(u"""\
        TO: {{email}}
        FROM: <EMAIL>

        Hello world
    """))

    # Simple database with two entries
    database_path = Path(tmpdir/"mailmerge_database.csv")
    database_path.write_text(textwrap.dedent(u"""\
        email
        <EMAIL>
        <EMAIL>
    """))

    # Simple unsecure server config
    config_path = Path(tmpdir/"mailmerge_server.conf")
    config_path.write_text(textwrap.dedent(u"""\
        [smtp_server]
        host = open-smtp.example.com
        port = 25
        ratelimit = 60
    """))

    # Run mailmerge
    before = datetime.datetime.now()
    with tmpdir.as_cwd():
        runner = click.testing.CliRunner(mix_stderr=False)
        result = runner.invoke(
            main, [
                "--no-limit",
                "--no-dry-run",
                "--output-format", "text",
            ]
        )
    after = datetime.datetime.now()
    assert after - before > datetime.timedelta(seconds=1)
    smtp = mock_SMTP.return_value.__enter__.return_value
    assert smtp.sendmail.call_count == 2
    assert result.exit_code == 0
    assert result.stderr == ""
    assert ">>> message 1 sent" in result.stdout
    assert ">>> rate limit exceeded, waiting ..." in result.stdout
    assert ">>> message 2 sent" in result.stdout

{'fraction_non_alphanumeric': 0.10714285714285714, 'fraction_numerical': 0.007950990615224193, 'mean_word_length': 2.6907166907166906, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 51, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2608505', 'n_tokens_mistral': 2417, 'n_tokens_neox': 2319, 'n_words': 589}