Sign in to follow this  
Followers 0
NSearch

Auto Email Attachments

15 posts in this topic

Does anyone know of a way to automatically send email with attachments? I do not want to send the mail by opening up outlook express and sending commands to the application. I would like to have the email sent "in the background".

Any suggestions will be much appreciated.

Thanks,

Stephen

Share this post


Link to post
Share on other sites



Does anyone know of a way to automatically send email with attachments?

Options:

write a wrapper for the command line utility blat. There may even be one on the site you can use

verbatim or as a starting point.

find a freeware com library supporting the methods you need ( i have yet to find one)

find a dll library and write dllcalls()

Someone has a sendmail udf that uses au3 tcp functions to talk to a smtp server, i haven't looked

at it, but it either has the capability or could be extended to do so.

Remember, if you are doing this w/ a udf a binary attachment must be "encoded" to meet the plaintext

SMTP protocol specification. This adds another layer --- not only do you have to mail the file, you have to prep it to be mailed.


Reading the help file before you post... Not only will it make you look smarter, it will make you smarter.

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

Hi Stephen

I was looking for the same thing and I could not find any example from the forums that would use plain SMTP codes, so I made my own improvements to the original _INetSmtpMail.

I added the file attachment part and an extra mail recipient to the code.

At the moment the code only support one file and one extra recipient.

First I added CC field for one extra recipient. It is possible to add even more recipients. All that need to be done is just send more RCPT TO commands and then also add the recipients to To/Cc/Bcc fields.

With the file attachment, first it needs to be encode to Base64.

Ward had made a good encoder for it, which can be found here: link

After that I added boundaries that would tell which part of the data is the message body and which is the file.

With more boundary fields it is possible have multiple attachments or have the message in HTML.

I hope this works for you who might need it.

Here is the full code:

#include <INet.au3>
#Include <File.au3>
#include <Array.au3>

$smtpServer = "smtp.somesmtpserver.com"
$fromName = "firstname lastname"
$fromAddress = "myname@myisp.com"
$toAddress = "some@address.com"
$ccAddress = "some.other@address.com"
$subject = "_INetSmtpMail2 Test"
$attachment = @ScriptDir & "\Test.txt"
$body = "Testing the email attachment and copy recipient"
$smtpResponse = _INetSmtpMail2($smtpServer, $fromName, $fromAddress, $toAddress, $ccAddress, $subject, $body, $attachment)
$err = @error
If $smtpResponse = 1 Then
    MsgBox(0, "Success!", "Mail sent", 0)
Else
    MsgBox(0, "Error!", "Mail failed with error code " & $err)
EndIf

;===============================================================================
;
; Function Name:    _INetSmtpMail2()
; Description:      Added support for one file attachment and one extra mail recipient from _INetSmtpMail
; Features:         File attachment and CC recipient
; Parameter(s):     $s_SmtpServer   - SMTP server
;                   $s_FromName     - Sender's email address
;                   $s_ToAddress    - Recepient's email address
;                   $s_CCAddress    - Recepient's email address 
;                   $s_Subject      - Subject
;                   $as_Body        - Message body
;                   $s_Attachment   - Path of the attachment file 
;                   $s_helo
;                   $s_first
;                   $b_trace
; Requirement(s):   INet.au3, File.au3, Array.au3
; Return Value(s):  On Success - Returns 1
;                   On Failure - Sends error code
;
;===============================================================================
Func _INetSmtpMail2($s_SmtpServer, $s_FromName, $s_FromAddress, $s_ToAddress, $s_CCAddress = "", $s_Subject = "", $as_Body = "", $s_Attachment = "", $s_helo = "", $s_first=-1, $b_trace = 0)
    ;Encoding attachment to base64
    If $s_Attachment = "" Then 
        Else
        Local $file = FileOpen($s_Attachment, 0)
        If $file = -1 Then
            MsgBox(48, "Error", "Unable to open file.")
            Exit
        EndIf
        $encodedFile = _Base64Encode(FileRead($file)) ; Encoding file to Base64
        FileClose($file)
        Dim $szDrive, $szDir, $szFName, $szExt
        _PathSplit($s_Attachment, $szDrive, $szDir, $szFName, $szExt)
        Local $s_fileName = $szFName & $szExt
        Local $fileSize = FileGetSize($s_Attachment)
    EndIf

    ;Variables
    Dim $szDrive, $szDir, $szFName, $szExt
    Local $boundary = "^_^" & Random(1, 32) & "^_^" ; Boundary marker for different Content Type
    Local $v_Socket
    Local $s_IPAddress
    Local $i_Count
    Local $s_Send[7]
    Local $s_ReplyCode[7];Return code from SMTP server indicating success

    If $s_SmtpServer = "" Or $s_FromAddress = "" Or $s_ToAddress = "" Or $s_FromName = "" Or StringLen($s_FromName) > 256 Then
        SetError(1)
        Return 0
    EndIf
    If $s_helo = "" Then $s_helo = @ComputerName
    If TCPStartup() = 0 Then
        SetError(2)
        Return 0
    EndIf
    StringRegExp($s_SmtpServer, "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)")
    If @extended Then
        $s_IPAddress = $s_SmtpServer
    Else
        $s_IPAddress = TCPNameToIP($s_SmtpServer)
    EndIf
    If $s_IPAddress = "" Then
        TCPShutdown()
        SetError(3)
        Return 0
    EndIf
    $v_Socket = TCPConnect($s_IPAddress, 25)
    If $v_Socket = -1 Then
        TCPShutdown()
        SetError(4)
        Return (0)
    EndIf

    $s_Send[0] = "EHLO " & $s_helo & @CRLF
    $s_ReplyCode[0] = "250"

    $s_Send[1] = "MAIL FROM: <" & $s_FromAddress & ">" & @CRLF
    $s_ReplyCode[1] = "250"
    $s_Send[2] = "RCPT TO: <" & $s_ToAddress & ">" & @CRLF
    $s_ReplyCode[2] = "250"
    If $s_CCAddress = "" Then
        $s_Send[3] = @CRLF
        $s_ReplyCode[3] = "500"
    Else
        $s_Send[3] = "RCPT TO: <" & $s_CCAddress & ">" & @CRLF ; CC Recipient
        $s_ReplyCode[3] = "250"
    EndIf
    $s_Send[4] = "DATA" & @CRLF
    $s_ReplyCode[4] = "354"

    Local $aResult = _Date_Time_GetTimeZoneInformation()
    Local $bias = -$aResult[1]/60
    Local $biasH = Int($bias)
    Local $biasM = 0
    If $biasH <> $bias Then $biasM =  Abs($bias - $biasH) * 60
    $bias =  StringFormat(" (%+.2d%.2d)", $biasH, $biasM)

    $data = _
            "From: " & $s_FromName & "<" & $s_FromAddress & ">" & @CRLF & _
            "To: " & "<" & $s_ToAddress & ">" & @CRLF & _
            "Cc: " & "<" & $s_CCAddress & ">" & @CRLF & _
            "Subject: " & $s_Subject & @CRLF & _
            "Importance: " & "Normal" & @CRLF & _
            "Mime-Version: 1.0" & @CRLF & _
            "Date: " & _DateDayOfWeek(@WDAY, 1) & ", " & @MDAY & " " & _DateToMonth(@MON, 1) & " " & @YEAR & " " & @HOUR & ":" & @MIN & ":" & @SEC & $bias & @CRLF & _
            "Content-Type: multipart/mixed;" & @CRLF & _ 
            ' boundary="' & $boundary & '"' & @CRLF & _ ; Boundary specified
            @CRLF & _
            "--" & $boundary & @CRLF & _    ; body part, first boundary "--xxxx"
            'Content-Type: text/plain;' & @CRLF & _ 
            'charset="iso-8859-1"' & @CRLF & _
            'Content-Transfer-Encoding: quoted-printable' & @CRLF & @CRLF & _
            $as_body & @CRLF
    If $s_Attachment = "" Then 
        Else
        $data =  $data & @CRLF & _
            "--" & $boundary & @CRLF & _ ; file attachment part, second boundary "--xxxx"
            'Content-Type: text/plain; name="<' & $s_fileName & '>"' & @CRLF & _ 
            'Content-Transfer-Encoding: base64' & @CRLF & _
            'Content-Disposition: attachment; filename="' & $s_fileName & '"' & @CRLF & _
            ' size=' & $fileSize & @CRLF & _
            @CRLF & _ 
            $encodedFile & @CRLF
    EndIf
    $data = $data & '--' & $boundary & '--' & @CRLF ; end of boundaries --xxxx--

    $s_Send[5] = $data

    $s_ReplyCode[5] = ""

    $s_Send[6] = @CRLF & "." & @CRLF
    $s_ReplyCode[6] = "250"

    ; open stmp session
    If _SmtpSend($v_Socket, $s_Send[0], $s_ReplyCode[0], $b_trace, "220", $s_first) Then
        SetError(50)
        Return 0
    EndIf
    ; send header
    For $i_Count = 1 To UBound($s_Send) - 2
        If _SmtpSend($v_Socket, $s_Send[$i_Count], $s_ReplyCode[$i_Count], $b_trace) Then
            SetError(50 + $i_Count)
            Return 0
        EndIf
    Next

    ; send body records (a record can be multiline : take care of a subline beginning with a dot should be ..)
    For $i_Count = 0 To UBound($as_Body) - 1
        ; correct line beginning with a dot
        If StringLeft($as_Body[$i_Count], 1) = "." Then $as_Body[$i_Count] = "." & $as_Body[$i_Count]

        If _SmtpSend($v_Socket, $as_Body[$i_Count] & @CRLF, "", $b_trace) Then
            SetError(500 + $i_Count)
            Return 0
        EndIf
    Next

    ; close the smtp session
    $i_Count = UBound($s_Send) - 1
    If _SmtpSend($v_Socket, $s_Send[$i_Count], $s_ReplyCode[$i_Count], $b_trace) Then
        SetError(5000)
        Return 0
    EndIf

    TCPCloseSocket($v_Socket)
    TCPShutdown()
    Return 1
EndFunc     ;==>_INetSmtpMail2

Func _Base64Encode($Data, $LineBreak = 76)
    Local $Opcode = "0x5589E5FF7514535657E8410000004142434445464748494A4B4C4D4E4F505152535455565758595A6162636465666768696A6B6C6D6E6F707172737475767778797A303132333435363738392B2F005A8B5D088B7D108B4D0CE98F0000000FB633C1EE0201D68A06880731C083F901760C0FB6430125F0000000C1E8040FB63383E603C1E60409C601D68A0688470183F90176210FB6430225C0000000C1E8060FB6730183E60FC1E60209C601D68A06884702EB04C647023D83F90276100FB6730283E63F01D68A06884703EB04C647033D8D5B038D7F0483E903836DFC04750C8B45148945FC66B80D0A66AB85C90F8F69FFFFFFC607005F5E5BC9C21000"

    Local $CodeBuffer = DllStructCreate("byte[" & BinaryLen($Opcode) & "]")
    DllStructSetData($CodeBuffer, 1, $Opcode)

    $Data = Binary($Data)
    Local $Input = DllStructCreate("byte[" & BinaryLen($Data) & "]")
    DllStructSetData($Input, 1, $Data)

    $LineBreak = Floor($LineBreak / 4) * 4
    Local $OputputSize = Ceiling(BinaryLen($Data) * 4 / 3) 
    $OputputSize = $OputputSize + Ceiling($OputputSize / $LineBreak) * 2 + 4

    Local $Ouput = DllStructCreate("char[" & $OputputSize & "]")
    DllCall("user32.dll", "none", "CallWindowProc", "ptr", DllStructGetPtr($CodeBuffer), _
                                                    "ptr", DllStructGetPtr($Input), _
                                                    "int", BinaryLen($Data), _
                                                    "ptr", DllStructGetPtr($Ouput), _
                                                    "uint", $LineBreak)
    Return DllStructGetData($Ouput, 1)
EndFunc     ;==>_Base64Encode
Edited by scrolli

Share this post


Link to post
Share on other sites

Hi Scrolli

Thanks for that code, works perfectly. Is there a possibility to have the mail sent with automatic acknowledgement from the recipient? Sorry to ask, I'm a newbie to AutoIt.

Thanks

Bertrand

Share this post


Link to post
Share on other sites

You mean the mail will ask for acknowledgement from the recipient that the mail has been received?

Share this post


Link to post
Share on other sites

Does anyone know of a way to automatically send email with attachments? I do not want to send the mail by opening up outlook express and sending commands to the application. I would like to have the email sent "in the background".

Any suggestions will be much appreciated.

Thanks,

Stephen

Hi Stephen

I was directed to the Code Cutter Wooltown http://www.autoitscript.com/forum/index.php?showtopic=89321&hl=wooltown&st=0 who has created a whole library of routines that manipulate Outlook where you can set the priority of emails multiple attachments etc etc it is well worth a look. Ant..

Share this post


Link to post
Share on other sites

Did you search the forum first? You are looking for what has already been accomplished. Search the forum for SMTP Mailer. There are several mailers out there. All you need to do is cut and paste the functions and automate them instead of using the gui.


[font="Verdana"] [size="2"]"[/size][/font]Failure is not an option -- it comes packaged with Windows"[font="Verdana"][size="2"] Gecko Web Browser[/size][/font][font="Verdana"][size="2"], [/size][/font][font="Verdana"][size="2"]Yahtzee![/size][/font][font="Verdana"][size="2"], Toolbar Launcher (like RocketDock)[/size][/font][font="Verdana"][size="2"]Internet Blocker, Simple Calculator, Local Weather, Easy GDI+ GUI [/size][/font][font="Verdana"][size="2"]Triangle Solver, TCP File Transfer, [/size][/font][font="Verdana"][size="2"]Valuater's Autoit Wrappers[/size][/font][font="Verdana"][size="3"][size="2"][size="2"]OOP In AutoIt[/size][/size][/size][/font][font="Verdana"][size="2"][size="1"]Using Windows XP SP3, 1GB RAM, AMD Athlon Processor @ 2.1 GHzCheck me out at gadgets.freehostrocket.com[/size][/size][/font]

Share this post


Link to post
Share on other sites

You mean the mail will ask for acknowledgement from the recipient that the mail has been received?

Yes, this is exactly what I need, but don't know if it is even possible.

Thanks

Bertrand

Share this post


Link to post
Share on other sites

Hi guys, I am using Scrolli's Library to send email attachments and it works perfectly on windows xp, but on windows 2003 I get an error I traced it to the encoding function but I have no idea how to fix it, can someone please help.

event viewer logs the following:

Faulting application AutoIt3.exe, version 3.3.4.0, faulting module unknown, version 0.0.0.0, fault address 0x01d7f648.

I think this is the offending code, its making a windows call in xp that work but in windows 2003 doesn't like it.

DllCall("user32.dll", "none", "CallWindowProc", "ptr", DllStructGetPtr($CodeBuffer), _

"ptr", DllStructGetPtr($Input), _

"int", BinaryLen($data), _

"ptr", DllStructGetPtr($Ouput), _

"uint", $LineBreak)

Return DllStructGetData($Ouput, 1)

Share this post


Link to post
Share on other sites

yes both machines are 32bit.

Share this post


Link to post
Share on other sites

Hmmm, I don't know the specific library / UDF, but I see $CodeBuffer being used. Maybe it's DEP related? Take a look here how I solved that for wards md5 ASM code.

Share this post


Link to post
Share on other sites

The code I am using is the one posted above that scrolli wrote. He is using the INet.au3 library and modified it so it can do attachments.

I will check the suggestion that you posted, thanks a bunch(after I come back from a meeting).

Share this post


Link to post
Share on other sites

#15 ·  Posted (edited)

So... today I log into the server and I get a pop up window for DEP I add the autoit .exe in the exception list and guess what "IT WORKS"

I wish that would pop up when you run the program, but all you get is:

Faulting application AutoIt3.exe, version 3.3.4.0, faulting module unknown, version 0.0.0.0, fault address 0x01d60df0.

Which translated into english means DEP stopped the .exe from running,

I love getting unrelated messages to what is really happening on the server

keeps my job secure.

Edited by Charly1r

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0