cancel
Showing results for 
Search instead for 
Did you mean: 
cancel

How To Send MIME Attachments Using EEM

4665
Views
4
Helpful
28
Comments

It is very easy to send email messages using EEM.  Often times, it is sufficient to simply include CLI output or other messages in the body of the email.  However, some output may be quite large, or you may have a need to send binary attachments (e.g. Embedded Packet Capture files).  In those cases, it would be better to use MIME encoding, and add the data as file attachments.  Here is a short proof-of-concept EEM script that demonstrates how to do this.

::cisco::eem::register_event_none

namespace import ::cisco::eem::*

namespace import ::cisco::lib::*

# First, create the headers and body of your message

set email_body_pre "Mailservername: $_email_server
From: $_email_from
To: $_email_to
Cc:
Subject: Email from Router $_router_name
MIME-Version: 1.0
Content-type: multipart/mixed; boundary=\"EEM_email_boundary\"
\n--EEM_email_boundary\n
\n--EEM_email_boundary
Content-Type: application/octet-stream
Content-Transfer-Encoding: Base64
Content-Disposition: attachment; filename=\"test.log\"\n\n"

# Then, read in the data you wish to attach.

if [catch {open "flash:test.log"} result] {
    error $result $errorInfo
}
set fd $result

# Encode that data using the built-in base64 library.
set email_b64 [::base64::encode [read $fd]]
close $fd

# Construct the final message with the headers, body, and MIME parts.

set email_body_mime "\n--EEM_email_boundary--"

set email_body [format "%s%s%s" $email_body_pre $email_b64 $email_body_mime]

# Send the email.

if [catch {smtp_send_email $email_body} result] {
    error $result $errorInfo
}

Comments
ideocisco
Beginner

Hi,

 

What if you need to send 2 attachments and add text in the body of the email?

 

Thanks,

Stéphane

Joe Clarke
Hall of Fame Cisco Employee

You just need to add more boundaries (i.e. more EEM_email_boundary sections).  The text body will come between the first two in $email_body_pre.

ideocisco
Beginner

Thanks for your fast response.

I am new to this, so please forgive my lack of knowledge.

Is this what you mean :

MIME-Version: 1.0
Content-type: multipart/mixed; boundary=\"EEM_email_boundary\"
\n--EEM_email_boundary\n
This is a test to appear in the body of the message
\n--EEM_email_boundary
Content-Type: application/octet-stream
Content-Transfer-Encoding: Base64
Content-Disposition: attachment; filename=\"test.log\"\n\n"
\n--EEM_email_boundary
Content-Type: application/octet-stream
Content-Transfer-Encoding: Base64
Content-Disposition: attachment; filename=\"test2.log\"\n\n"

Thanks,

Stéphane

Joe Clarke
Hall of Fame Cisco Employee

Yep.

ideocisco
Beginner

Hi,

Thanks this works perfectly nice.
Another question.
What if I wanted to attach text already in a variable. Is this possible?

Ex :
set email_attachment_1 "This is a test"
Content-Disposition: attachment; filename=\"Message.txt\"\n\n"
set email_b64 [::base64::encode [$email_attachment_1]]

Thanks,

Stéphane

Joe Clarke
Hall of Fame Cisco Employee

Yes, that will work as well.

ideocisco
Beginner

I get the following error :

Router#event manager run Test.tcl

invalid command name "
 Pool Tag: 21
 MAC Address                : AAAA.AAAA.AAAA
 No. of attempts to register: 0
 Unregister time            :
 Last register request time :
 Reason for state unregister:
         No registration request since last reboot/unregister

 Pool Tag: 22
 MAC Address                : BBBB.BBBB.BBBB
 No. of attempts to register: 0
 Unregister time            :
 Last register request time :
 Reason for state unregister:
         No registration request since last reboot/unregister

Router#"

    while executing
"$email_attachment_1"
    invoked from within
"if {$ata_down} {
  append email_pre "$msg"

  app..."
    (file "tmpsys:/eem_policy/Test.tcl" line 179)
Tcl policy execute failed: invalid command name "
 Pool Tag: 21
 MAC Address                : AAAA.AAAA.AAAA
 No. of attempts to register: 0
 Unregister time            :

 Last register request time :
 Reason for state unregister:
         No registration request since last reboot/unregister

 Pool Tag: 22
 MAC Address                : BBBB.BBBB.BBBB
 No. of attempts to register: 0
 Unregister time            :
 Last register request time :
 Reason for state unregister:
         No registration request since last reboot/unregister

 

$email_attachment_1 contains the following :

 Pool Tag: 21
 MAC Address                : AAAA.AAAA.AAAA
 No. of attempts to register: 0
 Unregister time            :
 Last register request time :
 Reason for state unregister:
         No registration request since last reboot/unregister

 Pool Tag: 22
 MAC Address                : BBBB.BBBB.BBBB
 No. of attempts to register: 0
 Unregister time            :
 Last register request time :
 Reason for state unregister:
         No registration request since last reboot/unregister

Joe Clarke
Hall of Fame Cisco Employee

You can't put brackets around your variable.  It should be:

set email_b64 [::base64::encode $email_attachment_1]

 

ideocisco
Beginner

Thank you Joseph.

You are truly the best contributer I have the please to chat with.

This is working like a charm.

Thanks,

Stéphane

ideocisco
Beginner

Hi,

When I try to have 2 attachments, I do not get the results expected. The first attachment is empty and the 2nd attachment contains the data of the 2 files.

Here is my code :

set email_pre "Mailservername: $_email_server
From: $_email_from
To: $_email_to
Cc:
Subject: Test 2 attachment
MIME-Version: 1.0
Content-type: multipart/mixed; boundary=\"EEM_email_boundary\"
\n--EEM_email_boundary\n
This is a test email with 2 attachments"
append email_pre "\n--EEM_email_boundary
Content-Type: application/octet-stream
Content-Transfer-Encoding: Base64
Content-Disposition: attachment; filename=\"test.log\"\n\n"

if [catch {open "flash:test.log"} result] {
    error $result $errorInfo
}
set fd $result
set email_b64 [::base64::encode [read $fd]]
close $fd

append email_pre "\n--EEM_email_boundary
Content-Type: application/octet-stream
Content-Transfer-Encoding: Base64
Content-Disposition: attachment; filename=\"test2.log\"\n\n"

if [catch {open "flash:test2.log"} result] {
    error $result $errorInfo
}
set fd $result
set email_b64_2 [::base64::encode [read $fd]]
close $fd

set email_body_mime "\n--EEM_email_boundary--"
set email_body [format "%s%s%s" $email_pre $email_b64 $email_b64_2 $email_body_mime]

if [catch {smtp_send_email $email_body} result] {
    error $result $errorInfo
}

Joe Clarke
Hall of Fame Cisco Employee

You need to have the boundaries between your attachments.  Appending another boundary to email_pre doesn't do you any good.  Best to gave email_pre be your initial headers and email body.  Then each attachment will start its boundary and MIME info.

ideocisco
Beginner

Hi,

Don't I have boudaries between my attachments :

append email_pre "\n--EEM_email_boundary
Content-Type: application/octet-stream
Content-Transfer-Encoding: Base64
Content-Disposition: attachment; filename=\"test.log\"\n\n"

append email_pre "\n--EEM_email_boundary
Content-Type: application/octet-stream
Content-Transfer-Encoding: Base64
Content-Disposition: attachment; filename=\"test2.log\"\n\n"

Joe Clarke
Hall of Fame Cisco Employee

No, because $email_pre is only included at the front of you email.  You construct the email as:

 

email_pre

email_b64

email_b64_2

email_body_mime

 

You need a boundary and MIME header before email_b64 and before email_b64_2.

ideocisco
Beginner

Hi,

So something like :
set email_pre2 "MIME-Version: 1.0
Content-type: multipart/mixed; boundary=\"EEM_email_boundary\"
\n--EEM_email_boundary\n
\n--EEM_email_boundary
Content-Type: application/octet-stream
Content-Transfer-Encoding: Base64
Content-Disposition: attachment; filename=\"test2.log\"\n\n"

set email_body_mime "\n--EEM_email_boundary--"
set email_body [format "%s%s%s%s%s%s" $email_pre $email_b64 $email_body_mime $email_pre2 $email_b64_2 $email_body_mime]

 

ideocisco
Beginner

Hi,

I am getting there.

The above code sends me three attachments.
The 2 log files and the Body message both in the message and as an attachment.