Hello together,
i want to configure CheckMK to send the default HTML Mails via API from Amazon SES.
Sending an Email via HTTPS API is quite Simple. Just a few Lines of Code and the pip Extension boto3.
Reason: Mails can be sent out directly over https and it usually works without opening Ports on the Firewall. It would open the way to deploy checkmk on any customer site and allowing to send Mails when https port 443 to the internet is reachable.
Is there any way to use the default Template from CheckMK for Sending Mails or do i really have to program my own Notification Script for my own including the whole E-Mail Template?
You have to create a custom notification script for it. In the Notification documentation we have an example to create notification scripts. Other than that you can have a look at other notification scripts like Servicenow and get an idea. The scripts are located under ~/share/check_mk/notifications.
Is it possible to make a copy of the original Mailing Script mail.py and the wato file (dont know which one it is).
I want to use the original Mailing format of checkmk Enterprise and just want to develop a new Sending Method to let CheckMK use Amazon SES over API as Method.
i copied the mail file and created a new File Called “mailses”
What do i have to do to copy the Wato Config for this Notification, to make the Configurable Variables Available for my copied notification plugin?
I want a copy of the Original Mail Plugin including all Features the Original HTML-Mail of CheckMK offers. I just modified the copied mail.py and added the Feature to send the mail over the Amazon-SES Api.
I just have a problem with the Feature
“Send seperate notifications to every recipient”
Because the module Names are hardcoded in the notify.py
split_contexts = (
plugin_name not in ["", "mail", "asciimail", "slack"] or
# params can be a list (e.g. for custom notificatios)
params.get("disable_multiplexing") or bulk)
My new Module has the Name “mailses”
How can i add the module to the this file without hardcoding this file? It would get overwritten with every checkmk Update.
The Problem now is, that every notification gets send seperately and not together.
A workaround was to copy the notify.py and change the 2 lines to get mailing and graphs working…
This works but is not the best and performant solution
It also can break the site after update
if __name__ == "__main__":
import shutil
homefolder=os.path.expanduser('~')
src="/opt/omd/versions/default/lib/python3/cmk/base/notify.py"
dst=homefolder + "/local/lib/python3/cmk/base/notify.py"
shutil.copyfile(src, dst)
with open(dst) as f:
if not 'mailses' in f.read():
search0='"mail", '
replace0='"mail", "mailses", '
search1='if plugin_name == "mail"'
replace1='if plugin_name == "mail" or plugin_name == "mailses"'
import fileinput
with fileinput.FileInput(dst, inplace=True, backup='.bak') as file:
for line in file:
line=line.replace(search0, replace0)
line=line.replace(search1, replace1)
print(line, end='')
main()
Hi,
i created a Pull Request, but im not sure if Checkmk will ever integrate it:
I tried to create an MKP Package but it doesnt make sense. The Plugin uses the original code from the Core Mail Plugin. If i would create an own mkp Package, i always need to implement all Changes and Security fixes to my own Plugin. I just extened the Mail Plugin with the Amazon SES definition and extened the wato plugin with all needed fields.
Anyway if someone wants to test with MKP, feel free…
#!/usr/bin/env python3
# HTML Email - K&P Computer
# Bulk: yes
# Argument 1: Full system path to the pnp4nagios index.php for fetching the graphs. Usually auto configured in OMD.
# Argument 2: HTTP-URL-Prefix to open Multisite. When provided, several links are added to the mail.
# Example: http://myserv01/prod
#
# This script creates a nifty HTML email in multipart format with
# attached graphs and such neat stuff. Sweet!
import botocore
import boto3
from cmk.notification_plugins.mail import *
def send_mail_amazonses( # pylint: disable=too-many-branches
message: Message, target: str, from_address: str, context: dict[str, str]
) -> int:
retry_possible = False
success = False
while not success:
SENDER = context["PARAMETER_FROM_ADDRESS"]
targetses = target.split(",")
if not "PARAMETER_AMAZONSES_SESREGION" in context:
context["PARAMETER_AMAZONSES_SESREGION"] = "eu-central-1"
if not "PARAMETER_AMAZONSES_SESCONFIG" in context:
context["PARAMETER_AMAZONSES_SESCONFIG"] = ""
configsettext = "Not defined"
else:
configsettext = context["PARAMETER_AMAZONSES_SESCONFIG"]
if not "PARAMETER_AMAZONSES_SESAPIKEY" in context:
sys.stderr.write("Error: Amazon API Key missing in configuration")
break
if not "PARAMETER_AMAZONSES_SESAPIPASSWORD" in context:
sys.stderr.write("Error: Amazon API Password missing in configuration")
# Connect to Amazon SES API
client = boto3.client('ses',region_name=context["PARAMETER_AMAZONSES_SESREGION"],aws_access_key_id=context["PARAMETER_AMAZONSES_SESAPIKEY"],aws_secret_access_key=context["PARAMETER_AMAZONSES_SESAPIPASSWORD"])
try:
response = client.send_raw_email(
Source=SENDER,
Destinations=targetses,
RawMessage={'Data': message.as_string()},
ConfigurationSetName=context["PARAMETER_AMAZONSES_SESCONFIG"]
)
success = True
print("Email sent! Message ID: " + response['MessageId'] + " | Used Configuration Set: " + configsettext + " | Used AWS Region: " + context["PARAMETER_AMAZONSES_SESREGION"]),
except botocore.exceptions.ClientError as error:
if error.response['Error']['Code'] == 'LimitExceededException':
sys.stderr.write("API call limit exceeded; backing off and retrying...")
break
else:
raise error
if success:
return 0
if retry_possible:
return 1
return 2
# TODO: Use EmailContent parameter.
def send_mail_kpc(message: Message, target: str, from_address: str, context: dict[str, str]) -> int:
return send_mail_amazonses(message, target, from_address, context)
return 0
def mainkpc() -> NoReturn:
content = (
BulkEmailContent(utils.read_bulk_contexts)
if bulk_mode
else SingleEmailContent(utils.collect_context)
)
if not content.mailto: # e.g. empty field in user database
sys.stderr.write("Cannot send HTML email: empty destination email address\n")
sys.exit(2)
m = multipart_mail(
content.mailto,
content.subject,
content.from_address,
content.reply_to,
content.content_txt,
content.content_html,
content.attachments,
)
try:
sys.exit(
send_mail_kpc(
m,
content.mailto,
content.from_address,
content.context,
)
)
except Exception as e:
sys.stderr.write("Unhandled exception: %s\n" % e)
# unhandled exception, don't retry this...
sys.exit(2)
###Use modified version only if Amazon SES is configured, else use the original code from CheckMK####
content = (
BulkEmailContent(utils.read_bulk_contexts)
if bulk_mode
else SingleEmailContent(utils.collect_context)
)
if "PARAMETER_AMAZONSES_SESAPIKEY" in content.context or "PARAMETER_AMAZONSES_SESAPIPASSWORD" in content.context or "PARAMETER_AMAZONSES_SESREGION" in content.context:
if __name__ == "__main__":
mainkpc()
else:
if __name__ == "__main__":
main()
mail.py
#!/usr/bin/env python3
# Copyright (C) 2019 tribe29 GmbH - License: GNU General Public License v2
# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and
# conditions defined in the file COPYING, which is part of this source code package.
# Argument 1: Full system path to the pnp4nagios index.php for fetching the graphs. Usually auto configured in OMD.
# Argument 2: HTTP-URL-Prefix to open Multisite. When provided, several links are added to the mail.
# Example: http://myserv01/prod
#
# This script creates a nifty HTML email in multipart format with
# attached graphs and such neat stuff. Sweet!
from cmk.gui.plugins.wato.notifications import *
####Amazon SES Fields####
amazonsesfields = [
(
"amazonses",
Transform(
Dictionary(
title="Send Mails with Amazon SES API",
elements=[
(
"sesapikey",
TextInput(
title=_("Amazon API Key"),
size=70,
allow_empty=False,
),
),
(
"sesapipassword",
Password(
title=_("Amazon API Password"),
size=70,
allow_empty=False,
),
),
(
"sesregion",
TextInput(
title=_("AWS Region"),
size=20,
allow_empty=False,
default_value="eu-central-1",
),
),
(
"sesconfig",
TextInput(
title=_("SES Configuration Set"),
size=20,
allow_empty=True,
),
),
],
help=_(
"All E-Mails will be Sent with the Amazon SES API"
),
),
),
),
]
@notification_parameter_registry.register
class NotificationParameterMail(NotificationParameter):
@property
def ident(self) -> str:
return "mail"
@property
def spec(self):
return Dictionary(
title=_("Create notification with the following parameters"),
# must be called at run time!!
elements=self._parameter_elements_kpc,
)
def _parameter_elements_kpc(self):
from cmk.gui.plugins.wato.notifications import _get_url_prefix_specs
from cmk.gui.plugins.wato.notifications import _vs_add_common_mail_elements
from cmk.gui.plugins.wato.notifications import local_site_url
from cmk.gui.plugins.wato.notifications import transform_to_valuespec_html_mail_url_prefix
from cmk.gui.plugins.wato.notifications import transform_from_valuespec_html_mail_url_prefix
elements = _vs_add_common_mail_elements(
[
(
"elements",
ListChoice(
title=_("Display additional information"),
choices=[
("omdsite", _("Site ID")),
("hosttags", _("Tags of the Host")),
("address", _("IP Address of Host")),
("abstime", _("Absolute Time of Alert")),
("reltime", _("Relative Time of Alert")),
("longoutput", _("Additional Plugin Output")),
("ack_author", _("Acknowledgement Author")),
("ack_comment", _("Acknowledgement Comment")),
("notification_author", _("Notification Author")),
("notification_comment", _("Notification Comment")),
("perfdata", _("Metrics")),
("graph", _("Time series graph")),
("notesurl", _("Custom Host/Service Notes URL")),
("context", _("Complete variable list (for testing)")),
],
default_value=["graph", "abstime", "address", "longoutput"],
),
),
(
"insert_html_section",
TextAreaUnicode(
title=_("Add HTML section above table (e.g. title, description…)"),
default_value="<HTMLTAG>CONTENT</HTMLTAG>",
cols=76,
rows=3,
),
),
(
"url_prefix",
_get_url_prefix_specs(
"http://" + socket.gethostname() + url_prefix() + "check_mk/",
request.is_ssl_request and "automatic_https" or "automatic_http",
),
),
(
"no_floating_graphs",
FixedValue(
value=True,
title=_("Display graphs among each other"),
totext=_("Graphs are shown among each other"),
help=_(
"By default all multiple graphs in emails are displayed floating "
"nearby. You can enable this option to show the graphs among each "
"other."
),
),
),
]
)
elements += amazonsesfields
if not cmk_version.is_raw_edition():
import cmk.gui.cee.plugins.wato.syncsmtp # pylint: disable=no-name-in-module
elements += cmk.gui.cee.plugins.wato.syncsmtp.cee_html_mail_smtp_sync_option
elements += [
(
"graphs_per_notification",
Integer(
title=_("Graphs per notification (default: 5)"),
label=_("Show up to"),
unit=_("graphs"),
help=_(
"Sets a limit for the number of graphs that are displayed in a notification."
),
default_value=5,
minvalue=0,
),
),
(
"notifications_with_graphs",
Integer(
title=_("Bulk notifications with graphs (default: 5)"),
label=_("Show graphs for the first"),
unit=_("Notifications"),
help=_(
"Sets a limit for the number of notifications in a bulk for which graphs "
"are displayed. If you do not use bulk notifications this option is ignored. "
"Note that each graph increases the size of the mail and takes time to render"
"on the monitoring server. Therefore, large bulks may exceed the maximum "
"size for attachements or the plugin may run into a timeout so that a failed "
"notification is produced."
),
default_value=5,
minvalue=0,
),
),
]
return elements