Alerts with Mailreceiver from messagefield

Hello Forum,

i asked a question some days ago about email notification which sould use an receiver from message field.
unfortunatly this topic was closed since nobody knew an answer, but im still on it.

Challenge:
use a field (like ${foreach backlog message}${message.fields.to}${end} ) as email receiver.

i was able to use the backlog message successfully as email-subject (with the above shown method).
But Graylog denies to use this as receiver.

This topic/question should be moved to “daily challnges” or “development” but i cant create there.

i can ensure that the used field is always present when the alert is triggerd.
Since graylog is validating the mail-receiver in notification-tab i cant even create it.

is it possible to implement another field (besides user or explicit email) to use a mail from message?

best regards,
coffee_is_life1337

Hello,

If I understand you correct, are you referring to this section of the Notification area?

@gsmith,

thats correct, but when i try to refer to a field (“to”) from a message its not working. If i try to use the notification receiver “to” field, graylog is throwing this error (message field “to” is filled with my correct email) :

The Graylog server encountered an error while trying to send an email. This is the detailed error message: org.apache.commons.mail.EmailException: javax.mail.internet.AddressException: Missing final ‘@domain’ in string ${message.fields.to}'' (javax.mail.internet.AddressException: Missing final '@domain' in string ${message.fields.to}’’)

if i use only ${message.to} i get following error (similar)

Notification:

//EDIT: Same with only “${to}” in Email recipients and “${foreach backlog message}${message.fields.to}${end}”.

Correct me if I’m wrong but your trying to use a Macro for an email account or use it as Cc?
I tested this but have the same results. Not 100% sure if graylog can process something like this yet

Just a thought, does the “to” field have a email address?

quote from first entry:
“i can ensure that the used field is always present when the alert is triggerd.”

but for clarification, yes, the “to”-field is always filled with a valid mail address.
The field is filled with pipeline-processors.

i can imagine, that graylog checks the mail before filling the variable or its out of boundaries to use a field from the original message there.

i want to use the alert as following:

we have postfix header and mime-header checks on wich our mailserver decides if the mail will be delivered, redirected or rejected. (works fine, just to get the whole picture)
currently itjujst do it’s things and nobody knows if a mail was redirected (besides the admins who are working with graylog and see the logs/dashboard).
i want to triggern an alert if a mail was rejected (alert triggers, everything fine)
now i want to generate an email nto notify the user which should have received the redirected/rejected message.
just to inform him: "hey, there was an email for you, but it was redirected because of "

the reason, the original recipient and the action are all in graylog, each got a field.
now i just want to use the “to”-field to send the alert template to this specific user.

best regards,
coffee_is_life1337

Hello,

Sorry I have missed that.

I understand now, actually that is something similar here but were taking the long route. For our redirected/rejected notification come from the mail.log then filtered to a stream. once processed then the proper tech gets the alert if it was redirected or dropped. Unfortunately, I’m not sure how to solve your issue.

Sorry I cant be more help.

You could likely script a response (Enterprise required) that could be sent to the contents of a field. You can get the enterprise license free if you are under 5GB a day…

2 Likes

Hello @tmacgbay,

im using enterprise since 1 week and didnt notice the new script callback function :slight_smile:
after some try and error i got the following, based on the script from documentation:
(still on python2, so i need to add “print” as function to use it)

#!/usr/bin/env python2
from __future__ import print_function
import json
import sys
import subprocess

# Main function
if __name__ == "__main__":

    # Print out all input arguments.
    action = sys.argv[1]
    f = open("/tmp/testnotification.log", "a")
    f.write("Action: " + action + "\n")
    for i in sys.argv[2:]:
      f.write("Arguments: " + i + "\n")
    f.close
    # Turn stdin.readlines() array into a string
    std_in_string = ''.join(sys.stdin.readlines())


    # Load JSON
    event_data = json.loads(std_in_string)

    # Extract Message Backlog field from JSON.
    f = open("/tmp/testnotification.log", "a")
    f.write("\nBacklog:\n")
    arg_string=""
    for message in event_data["backlog"]:
        try:
          f.write("custom once to: " + message["fields"]["to"] + "\n")
          my_to = message["fields"]["to"]
          arg_string+='-t \'' + my_to + '\' '
        except:
          pass
        try:
          f.write("custom once from: " + message["fields"]["from"] + "\n")
          my_from = message["fields"]["from"]
          arg_string+='-f \'' + my_from + '\' '
        except:
          pass
        try:
          f.write("custom once MailAction: " + message["fields"]["MailAction"] + "\n")
          my_mailaction = message["fields"]["MailAction"]
          arg_string+='-m \'' + my_mailaction + '\' '
        except:
          pass
        try:
          f.write("custom once Return: " + message["fields"]["ReturnMessage"] + "\n")
          my_returnmessage = message["fields"]["ReturnMessage"]
          arg_string+='-r \'' + my_returnmessage + '\' '
        except:
          pass
        try:
          f.write("custom once blocked: " + message["fields"]["BlockedFile"] + "\n")
          my_blocked_file = message["fields"]["BlockedFile"].replace('"', '')
          arg_string+='-b \'' + my_blocked_file + '\' '
        except:
          pass
        try:
          f.write("custom once Time: " + message["timestamp"] + "\n")
          my_time = message["timestamp"]
          arg_string+='-z \'' + my_time + '\' '
        except:
          pass
        f.close

    if action == "mail_to_user":
      f = open("/tmp/testnotification.log", "a")
      f.write("Start action: " + action + "\n")
      #script = '/usr/share/graylog-server/scripts/' + action + '.sh ' + ' -a \'' + action + '\' -t \'' + my_to + '\' -f \'' + my_from + '\' -m \'' + my_mailaction + '\' -r \'' + my_returnmessage + '\' -z \'' + my_time + '\' -b \'' + my_blocked_file + '\''
      script = '/usr/share/graylog-server/scripts/' + action + '.sh ' + arg_string
      f.write("cmd_line: " + script + "\n")
      rc = subprocess.Popen(script, shell=True)
      f.write("============================================" + "\n")
      f.close

    # Return an exit value. Zero is success, non-zero indicates failure.
    exit(0)


The bash-script which is called looks like following:

#!/bin/bash
##test callback
while getopts f:t:m:r:b:z:a: option; do
  case "${option}" in
        a) action=${OPTARG};;
        m) mailaction=${OPTARG};;
        t) to=${OPTARG};;
        f) from=${OPTARG};;
        r) returnmsg=${OPTARG};;
        b) blocked_file=${OPTARG};;
        z) my_time="$(date -d "${OPTARG}" +'%d-%m-%Y %H:%M')";;
        :  ) echo "Missing option argument for -$OPTARG" >&2; exit 1;;
        *  ) echo "Unimplemented option: -$OPTARG" >&2; exit 1;;
  esac
done
# echo "from bash: " >> /tmp/testnotification.log
# echo "a: $action
#m: $mailaction
#t: $to
#f: $from
#b: $blocked_file
#r: $returnmsg
#z: $my_time
#
#start mutt" >> /tmp/testnotification.log

echo -e "
Title:\t\tMail von ${from} blockiert

Wann:\t\t${my_time}
Von:\t\t${from}
An:\t\t${to}
Anhang:\t\t${blocked_file}

Rückmeldung:\t${returnmsg}


mit freudlichen Grüßen
IT-Team
" >> /tmp/$$_mailtext.txt

mutt -e 'set content_type="text/plain" charset="utf-8" realname="IT-Team" from=noreply@MY_DOMAIN' $to -s"Mail was $mailaction" < /tmp/$$_mailtext.txt

rm -f /tmp/$$_mailtext.txt

The generated mail looks like this:

the python-script can be used to parse any fields and use them in other scripts (since im much better on bash than python its simpler for me to call bash-scripts for the actual callback and use the python-script as “parser-only” :smiley:

This works fine - thanks for the hint @tmacgbay

//EDIT: notification is set with a static argv:

//EDIT2:
updated the python_parser-script to dynamic building of the cmd_args
this way, there is no chance in calling the bash-script with unset vars - could be enhanced further by skip setting explicit vars for each field and just add

arg_string+='-b \'' + message["fields"]["BlockedFile"].replace('"', '') + '\' '

or

arg_string+='-m \'' + message["fields"]["MailAction"] + '\' '

instead of the var “my_mailaction” or “my_blocked_file” - but this is more readable and can be changed by whoever is using this script :slight_smile:

best regards,
coffee_is_life

3 Likes

Great!! Thanks for posting your work for others!

I must say that’s pretty amazing, Nice Job :smiley:

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.