Ejemplo n.º 1
0
 def test_url_encode(self):
     url_dict = {'url': 'http://myapp/my%20test/'}
     self.assertEqual(
         python_utils.url_encode(url_dict, doseq=True),
         'url=http%3A%2F%2Fmyapp%2Fmy%2520test%2F')
     self.assertEqual(
         python_utils.url_encode(url_dict, doseq=False),
         'url=http%3A%2F%2Fmyapp%2Fmy%2520test%2F')
Ejemplo n.º 2
0
def set_url_query_parameter(url, param_name, param_value):
    """Set or replace a query parameter, and return the modified URL.

    Args:
        url: str. URL string which contains the query parameter.
        param_name: str. Parameter name to be removed.
        param_value: str. Set the parameter value, if it exists.

    Returns:
        str. Formated URL that has query parameter set or replaced.

    Raises:
        Exception. If the query parameter sent is not of string type,
            them this exception is raised.
    """
    if not isinstance(param_name, python_utils.BASESTRING):
        raise Exception(
            'URL query parameter name must be a string, received %s'
            % param_name)

    scheme, netloc, path, query_string, fragment = python_utils.url_split(url)
    query_params = python_utils.parse_query_string(query_string)

    query_params[param_name] = [param_value]
    new_query_string = python_utils.url_encode(query_params, doseq=True)

    return python_utils.url_unsplit(
        (scheme, netloc, path, new_query_string, fragment))
Ejemplo n.º 3
0
def post_to_mailgun(data):
    """Send POST HTTP request to mailgun api. This method is adopted from
    the requests library's post method.

    Args:
        - data: dict. The data to be sent in the request's body.

    Returns:
         Response from the server. The object is a file-like object.
         https://docs.python.org/2/library/urllib2.html
    """
    if not feconf.MAILGUN_API_KEY:
        raise Exception('Mailgun API key is not available.')

    if not feconf.MAILGUN_DOMAIN_NAME:
        raise Exception('Mailgun domain name is not set.')

    encoded = base64.b64encode(b'api:%s' % feconf.MAILGUN_API_KEY).strip()
    auth_str = 'Basic %s' % encoded
    header = {'Authorization': auth_str}
    server = (
        'https://api.mailgun.net/v3/%s/messages' % feconf.MAILGUN_DOMAIN_NAME)
    data = python_utils.url_encode(data)
    req = python_utils.url_request(server, data, header)
    return python_utils.url_open(req)
Ejemplo n.º 4
0
def send_email_to_recipients(sender_email,
                             recipient_emails,
                             subject,
                             plaintext_body,
                             html_body,
                             bcc=None,
                             reply_to=None,
                             recipient_variables=None):
    """Send POST HTTP request to mailgun api. This method is adopted from
    the requests library's post method.

    Args:
        sender_email: str. The email address of the sender. This should be in
            the form 'SENDER_NAME <SENDER_EMAIL_ADDRESS>' or
            'SENDER_EMAIL_ADDRESS'. Must be utf-8.
        recipient_emails: list(str). The email addresses of the recipients.
            Must be utf-8.
        subject: str. The subject line of the email, Must be utf-8.
        plaintext_body: str. The plaintext body of the email. Must be utf-8.
        html_body: str. The HTML body of the email. Must fit in a datastore
            entity. Must be utf-8.
        bcc: list(str)|None. Optional argument. List of bcc emails.
        reply_to: str|None. Optional argument. Reply address formatted like
            “reply+<reply_id>@<incoming_email_domain_name>
            reply_id is the unique id of the sender.
        recipient_variables: dict|None. Optional argument. If batch sending
            requires differentiating each email based on the recipient, we
            assign a unique id to each recipient, including info relevant to
            that recipient so that we can reference it when composing the
            email like so:
                recipient_variables =
                    {"*****@*****.**": {"first":"Bob", "id":1},
                     "*****@*****.**": {"first":"Alice", "id":2}}
                subject = 'Hey, %recipient.first%’
            More info about this format at:
            https://documentation.mailgun.com/en/
                latest/user_manual.html#batch-sending.

    Raises:
        Exception. The mailgun api key is not stored in
            feconf.MAILGUN_API_KEY.
        Exception. The mailgun domain name is not stored in
            feconf.MAILGUN_DOMAIN_NAME.

    Returns:
        bool. Whether the emails are sent successfully.
    """
    if not feconf.MAILGUN_API_KEY:
        raise Exception('Mailgun API key is not available.')

    if not feconf.MAILGUN_DOMAIN_NAME:
        raise Exception('Mailgun domain name is not set.')

    # To send bulk emails we pass list of recipients in 'to' paarameter of
    # post data. Maximum limit of recipients per request is 1000.
    # For more detail check following link:
    # https://documentation.mailgun.com/user_manual.html#batch-sending
    recipient_email_lists = [
        recipient_emails[i:i + 1000]
        for i in python_utils.RANGE(0, len(recipient_emails), 1000)
    ]
    for email_list in recipient_email_lists:
        data = {
            'from': sender_email,
            'subject': subject,
            'text': plaintext_body,
            'html': html_body
        }

        data['to'] = email_list[0] if len(email_list) == 1 else email_list

        if bcc:
            data['bcc'] = bcc[0] if len(bcc) == 1 else bcc

        if reply_to:
            data['h:Reply-To'] = reply_to

        # 'recipient-variable' in post data forces mailgun to send individual
        # email to each recipient (This is intended to be a workaround for
        # sending individual emails).
        data['recipient_variables'] = recipient_variables or {}

        encoded = base64.b64encode(b'api:%s' % feconf.MAILGUN_API_KEY).strip()
        auth_str = 'Basic %s' % encoded
        header = {'Authorization': auth_str}
        server = (('https://api.mailgun.net/v3/%s/messages') %
                  feconf.MAILGUN_DOMAIN_NAME)
        encoded_url = python_utils.url_encode(data)
        req = python_utils.url_request(server, encoded_url, header)
        resp = python_utils.url_open(req)
        # The function url_open returns a file_like object that can be queried
        # for the status code of the url query. If it is not 200, the mail query
        # failed so we return False (this function did not complete
        # successfully).
        if resp.getcode() != 200:
            return False
    return True