From 94e95d879577139fcd24b24105485ef256b214d7 Mon Sep 17 00:00:00 2001 From: Jonathan Davila Date: Fri, 29 Jul 2016 22:17:56 -0400 Subject: [PATCH] Updates to Sendgrid Module (#1275) --- .../modules/extras/notification/sendgrid.py | 162 +++++++++++++++--- 1 file changed, 135 insertions(+), 27 deletions(-) diff --git a/lib/ansible/modules/extras/notification/sendgrid.py b/lib/ansible/modules/extras/notification/sendgrid.py index 1bac1e5f724..7e4593a9a90 100644 --- a/lib/ansible/modules/extras/notification/sendgrid.py +++ b/lib/ansible/modules/extras/notification/sendgrid.py @@ -32,13 +32,17 @@ notes: - "Like the other notification modules, this one requires an external dependency to work. In this case, you'll need an active SendGrid account." + - "In order to use api_key, cc, bcc, attachments, from_name, html_body, headers + you must pip install sendgrid" +requirements: + - sendgrid python library options: username: description: - username for logging into the SendGrid account required: true password: - description: + description: - password that corresponds to the username required: true from_address: @@ -53,6 +57,35 @@ options: description: - the desired subject for the email required: true + api_key: + description: + - sendgrid API key to use instead of username/password + version_added: 2.1 + cc: + description: + - a list of email addresses to cc + version_added: 2.1 + bcc: + description: + - a list of email addresses to bcc + version_added: 2.1 + attachments: + description: + - a list of relative or explicit paths of files you want to attach (7MB limit as per SendGrid docs) + version_added: 2.1 + from_name: + description: + - the name you want to appear in the from field, i.e 'John Doe' + version_added: 2.1 + html_body: + description: + - whether the body is html content that should be rendered + version_added: 2.1 + choices: [True, False] + headers: + description: + - a dict to pass on as headers + version_added: 2.1 author: "Matt Makai (@makaimc)" ''' @@ -87,26 +120,72 @@ EXAMPLES = ''' # import urllib -def post_sendgrid_api(module, username, password, from_address, to_addresses, - subject, body): - SENDGRID_URI = "https://api.sendgrid.com/api/mail.send.json" - AGENT = "Ansible" - data = {'api_user': username, 'api_key':password, - 'from':from_address, 'subject': subject, 'text': body} - encoded_data = urllib.urlencode(data) - to_addresses_api = '' - for recipient in to_addresses: - if isinstance(recipient, unicode): - recipient = recipient.encode('utf-8') - to_addresses_api += '&to[]=%s' % recipient - encoded_data += to_addresses_api - - headers = { 'User-Agent': AGENT, - 'Content-type': 'application/x-www-form-urlencoded', - 'Accept': 'application/json'} - return fetch_url(module, SENDGRID_URI, data=encoded_data, headers=headers, method='POST') - +try: + import sendgrid + HAS_SENDGRID = True +except ImportError: + HAS_SENDGRID = False +def post_sendgrid_api(module, username, password, from_address, to_addresses, + subject, body, api_key=None, cc=None, bcc=None, attachments=None, + html_body=False, from_name=None, headers=None): + + if not HAS_SENDGRID: + SENDGRID_URI = "https://api.sendgrid.com/api/mail.send.json" + AGENT = "Ansible" + data = {'api_user': username, 'api_key':password, + 'from':from_address, 'subject': subject, 'text': body} + encoded_data = urllib.urlencode(data) + to_addresses_api = '' + for recipient in to_addresses: + if isinstance(recipient, unicode): + recipient = recipient.encode('utf-8') + to_addresses_api += '&to[]=%s' % recipient + encoded_data += to_addresses_api + + headers = { 'User-Agent': AGENT, + 'Content-type': 'application/x-www-form-urlencoded', + 'Accept': 'application/json'} + return fetch_url(module, SENDGRID_URI, data=encoded_data, headers=headers, method='POST') + else: + + if api_key: + sg = sendgrid.SendGridClient(api_key) + else: + sg = sendgrid.SendGridClient(username, password) + + message = sendgrid.Mail() + message.set_subject(subject) + + for recip in to_addresses: + message.add_to(recip) + + if cc: + for recip in cc: + message.add_cc(recip) + if bcc: + for recip in bcc: + message.add_bcc(recip) + + if headers: + message.set_headers(headers) + + if attachments: + for f in attachments: + name = os.path.basename(f) + message.add_attachment(name, f) + + if from_name: + message.set_from('%s <%s.' % (from_name, from_address)) + else: + message.set_from(from_address) + + if html_body: + message.set_html(body) + else: + message.set_text(body) + + return sg.send(message) # ======================================= # Main # @@ -114,28 +193,57 @@ def post_sendgrid_api(module, username, password, from_address, to_addresses, def main(): module = AnsibleModule( argument_spec=dict( - username=dict(required=True), - password=dict(required=True, no_log=True), + username=dict(required=False), + password=dict(required=False, no_log=True), + api_key=dict(required=False, no_log=True), + bcc=dict(required=False, type='list'), + cc=dict(required=False, type='list'), + headers=dict(required=False, type='dict'), from_address=dict(required=True), + from_name=dict(required=False), to_addresses=dict(required=True, type='list'), subject=dict(required=True), body=dict(required=True), + html_body=dict(required=False, default=False, type='bool'), + attachments=dict(required=False, type='list') ), - supports_check_mode=True + supports_check_mode=True, + mutually_exclusive = [ + ['api_key', 'password'], + ['api_key', 'username'] + ], + required_together = [['username', 'password']], ) username = module.params['username'] password = module.params['password'] + api_key = module.params['api_key'] + bcc = module.params['bcc'] + cc = module.params['cc'] + headers = module.params['headers'] + from_name = module.params['from_name'] from_address = module.params['from_address'] to_addresses = module.params['to_addresses'] subject = module.params['subject'] body = module.params['body'] + html_body = module.params['html_body'] + attachments = module.params['attachments'] - response, info = post_sendgrid_api(module, username, password, - from_address, to_addresses, subject, body) - if info['status'] != 200: - module.fail_json(msg="unable to send email through SendGrid API: %s" % info['msg']) + sendgrid_lib_args = [api_key, bcc, cc, headers, from_name, html_body, attachments] + + if any(lib_arg != None for lib_arg in sendgrid_lib_args) and not HAS_SENDGRID: + module.fail_json(msg='You must install the sendgrid python library if you want to use any of the following arguments: api_key, bcc, cc, headers, from_name, html_body, attachments') + response, info = post_sendgrid_api(module, username, password, + from_address, to_addresses, subject, body, attachments=attachments, + bcc=bcc, cc=cc, headers=headers, html_body=html_body, api_key=api_key) + + if not HAS_SENDGRID: + if info['status'] != 200: + module.fail_json(msg="unable to send email through SendGrid API: %s" % info['msg']) + else: + if response != 200: + module.fail_json(msg="unable to send email through SendGrid API: %s" % info['message']) module.exit_json(msg=subject, changed=False)