From 2dab6cbb0e63e3f925441c56cc0126b1f3ca656e Mon Sep 17 00:00:00 2001 From: Philipp Schmitt Date: Wed, 8 Feb 2017 07:22:19 +0100 Subject: [PATCH] Mailgun notify service (#5782) * Mailgun notify service * Update dependency to version 1.3 - The provided credentials (including the domain) are now checked during startup, as requested by @balloob - The domain name is now optional - There's a new config item "sandbox" which indicates whether to use the sandboxed domain in case the domain is not set * Fix a few lint issues * Disable lint check no-value-for-parameter --- .coveragerc | 1 + homeassistant/components/notify/mailgun.py | 109 +++++++++++++++++++++ homeassistant/const.py | 1 + requirements_all.txt | 3 + 4 files changed, 114 insertions(+) create mode 100644 homeassistant/components/notify/mailgun.py diff --git a/.coveragerc b/.coveragerc index 251d9a7b6dc..2f1b0d1e857 100644 --- a/.coveragerc +++ b/.coveragerc @@ -258,6 +258,7 @@ omit = homeassistant/components/notify/kodi.py homeassistant/components/notify/lannouncer.py homeassistant/components/notify/llamalab_automate.py + homeassistant/components/notify/mailgun.py homeassistant/components/notify/matrix.py homeassistant/components/notify/message_bird.py homeassistant/components/notify/nfandroidtv.py diff --git a/homeassistant/components/notify/mailgun.py b/homeassistant/components/notify/mailgun.py new file mode 100644 index 00000000000..4765bd6893a --- /dev/null +++ b/homeassistant/components/notify/mailgun.py @@ -0,0 +1,109 @@ +""" +Support for the Mailgun mail service. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/notify.mailgun/ +""" +import logging + +import voluptuous as vol + +from homeassistant.components.notify import ( + PLATFORM_SCHEMA, BaseNotificationService, + ATTR_TITLE, ATTR_TITLE_DEFAULT, ATTR_DATA) +from homeassistant.const import (CONF_TOKEN, CONF_DOMAIN, + CONF_RECIPIENT, CONF_SENDER) +import homeassistant.helpers.config_validation as cv + +_LOGGER = logging.getLogger(__name__) +REQUIREMENTS = ['https://github.com/pschmitt/pymailgun/' + 'archive/1.3.zip#' + 'pymailgun==1.3'] + +# Images to attach to notification +ATTR_IMAGES = 'images' + +# Configuration item for the domain to use. +CONF_SANDBOX = 'sandbox' + +# Default sender name +DEFAULT_SENDER = 'hass@{domain}' +# Default sandbox value +DEFAULT_SANDBOX = False + +# pylint: disable=no-value-for-parameter +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_TOKEN): cv.string, + vol.Required(CONF_RECIPIENT): vol.Email(), + vol.Optional(CONF_DOMAIN): cv.string, + vol.Optional(CONF_SENDER): vol.Email(), + vol.Optional(CONF_SANDBOX, default=DEFAULT_SANDBOX): cv.boolean, +}) + + +def get_service(hass, config, discovery_info=None): + """Get the Mailgun notification service.""" + mailgun_service = MailgunNotificationService(config.get(CONF_DOMAIN), + config.get(CONF_SANDBOX), + config.get(CONF_TOKEN), + config.get(CONF_SENDER), + config.get(CONF_RECIPIENT)) + if mailgun_service.connection_is_valid(): + return mailgun_service + else: + return None + + +class MailgunNotificationService(BaseNotificationService): + """Implement a notification service for the Mailgun mail service.""" + + def __init__(self, domain, sandbox, token, sender, recipient): + """Initialize the service.""" + self._client = None # Mailgun API client + self._domain = domain + self._sandbox = sandbox + self._token = token + self._sender = sender + self._recipient = recipient + + def initialize_client(self): + """Initialize the connection to Mailgun.""" + from pymailgun import Client + self._client = Client(self._token, self._domain, self._sandbox) + _LOGGER.debug('Mailgun domain: %s', self._client.domain) + self._domain = self._client.domain + if not self._sender: + self._sender = DEFAULT_SENDER.format(domain=self._domain) + + def connection_is_valid(self): + """Check whether the provided credentials are valid.""" + from pymailgun import (MailgunCredentialsError, MailgunDomainError) + try: + self.initialize_client() + except MailgunCredentialsError: + _LOGGER.exception('Invalid credentials') + return False + except MailgunDomainError as mailgun_error: + _LOGGER.exception(mailgun_error) + return False + return True + + def send_message(self, message="", **kwargs): + """Send a mail to the recipient.""" + from pymailgun import MailgunError + subject = kwargs.get(ATTR_TITLE, ATTR_TITLE_DEFAULT) + data = kwargs.get(ATTR_DATA) + files = data.get(ATTR_IMAGES) if data else None + + try: + # Initialize the client in case it was not. + if self._client is None: + self.initialize_client() + resp = self._client.send_mail(sender=self._sender, + to=self._recipient, + subject=subject, + text=message, + files=files) + _LOGGER.debug('Message sent: %s', resp) + except MailgunError as mailgun_error: + _LOGGER.exception('Failed to send message: %s', mailgun_error) diff --git a/homeassistant/const.py b/homeassistant/const.py index ac5aeec581f..eda303a552e 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -82,6 +82,7 @@ CONF_DEVICES = 'devices' CONF_DISARM_AFTER_TRIGGER = 'disarm_after_trigger' CONF_DISCOVERY = 'discovery' CONF_DISPLAY_OPTIONS = 'display_options' +CONF_DOMAIN = 'domain' CONF_DOMAINS = 'domains' CONF_ELEVATION = 'elevation' CONF_EMAIL = 'email' diff --git a/requirements_all.txt b/requirements_all.txt index a9056817036..5118d9351cb 100755 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -248,6 +248,9 @@ https://github.com/nkgilley/python-ecobee-api/archive/4856a704670c53afe1882178a8 # homeassistant.components.notify.joaoapps_join https://github.com/nkgilley/python-join-api/archive/3e1e849f1af0b4080f551b62270c6d244d5fbcbd.zip#python-join-api==0.0.1 +# homeassistant.components.notify.mailgun +https://github.com/pschmitt/pymailgun/archive/1.3.zip#pymailgun==1.3 + # homeassistant.components.switch.edimax https://github.com/rkabadi/pyedimax/archive/365301ce3ff26129a7910c501ead09ea625f3700.zip#pyedimax==0.1