Пример #1
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)
Пример #2
0
def download_and_unzip_files(
        source_url, target_parent_dir, zip_root_name, target_root_name):
    """Downloads a zip file, unzips it, and saves the result in a given dir.

    The download occurs only if the target directory that the zip file unzips
    to does not exist.

    NB: This function assumes that the root level of the zip file has exactly
    one folder.

    Args:
        source_url: str. The URL from which to download the zip file.
        target_parent_dir: str. The directory to save the contents of the zip
            file to.
        zip_root_name: str. The name of the top-level folder in the zip
            directory.
        target_root_name: str. The name that the top-level folder should be
            renamed to in the local directory.
    """
    if not os.path.exists(os.path.join(target_parent_dir, target_root_name)):
        python_utils.PRINT('Downloading and unzipping file %s to %s ...' % (
            zip_root_name, target_parent_dir))
        common.ensure_directory_exists(target_parent_dir)

        python_utils.url_retrieve(source_url, filename=TMP_UNZIP_PATH)

        try:
            with zipfile.ZipFile(TMP_UNZIP_PATH, 'r') as zfile:
                zfile.extractall(path=target_parent_dir)
            os.remove(TMP_UNZIP_PATH)
        except Exception:
            if os.path.exists(TMP_UNZIP_PATH):
                os.remove(TMP_UNZIP_PATH)

            # Some downloads (like jqueryui-themes) may require a user-agent.
            req = python_utils.url_request(source_url, None, {})
            req.add_header('User-agent', 'python')
            # This is needed to get a seekable filestream that can be used
            # by zipfile.ZipFile.
            file_stream = python_utils.string_io(
                buffer_value=python_utils.url_open(req).read())
            with zipfile.ZipFile(file_stream, 'r') as zfile:
                zfile.extractall(path=target_parent_dir)

        # Rename the target directory.
        os.rename(
            os.path.join(target_parent_dir, zip_root_name),
            os.path.join(target_parent_dir, target_root_name))

        python_utils.PRINT('Download of %s succeeded.' % zip_root_name)
Пример #3
0
def lookup_pr(owner, repo, pull_number):
    """Lookup a PR using the GitHub API.

    Args:
        owner: str. Owner of the repository the PR is in.
        repo: str. Repository the PR is in.
        pull_number: str. PR number.

    Returns:
        dict. JSON object returned by the GitHub API v3. This is an
        empty dictionary if the response code from the GitHub API is not
        200.
    """
    request = python_utils.url_request(
        GITHUB_API_PR_ENDPOINT % (owner, repo, pull_number), None,
        {'Accept': 'application/vnd.github.v3+json'})
    response = python_utils.url_open(request)
    if response.getcode() != 200:
        return {}
    pr = json.load(response)
    response.close()
    return pr
Пример #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
Пример #5
0
 def test_url_request(self):
     response = python_utils.url_request('http://www.google.com', None, {})
     self.assertEqual(response.get_full_url(), 'http://www.google.com')