Sign in to follow this  
Followers 0

how to send an email with an attachment in exchange

13 posts in this topic

Posted (edited)

I've already searched and everyone else is using the code that starts up outlook and what not. That is not they way I want to do it. My code below already works and it sends an email without any user interaction. what I want to do is add an attachment. The other method people use is to add the .attachment.add("file"), but I'm not sure how to integrate it into my existing code.

#include <INet.au3>

$s_SmtpServer="MYSMTPSERVER"
$s_FromName="Test Name"
$s_FromAddress="noreply@mail.org"
$s_ToAddress="account@mail.org"
$s_Subject="Errors have been detected"
Dim $as_Body[1]
$as_Body[0]="One or more accounts have errors"
$s_helo="HELO"
$b_trace=-1

$Response = _INetSmtpMail ( $s_SmtpServer, $s_FromName, $s_FromAddress, $s_ToAddress ,$s_Subject ,$as_Body, $s_helo, $b_trace)

$err = @error
If $Response = 1 Then
    MsgBox(0, "Success!", "Mail sent")
Else
    MsgBox(0, "Error!", "Mail failed with error code " & $err)
EndIf
Edited by kor

Share this post


Link to post
Share on other sites



Posted

Search for _INetSmtpMail() in Examples.

Jos

Share this post


Link to post
Share on other sites

Posted (edited)

I tried this code but now the emails aren't getting sent. My previous code did not need a username and password so I'm unsure what I need to be using as a user & password with the new code.

;
;##################################
; Include
;##################################
#Include<file.au3>
;##################################
; Variables
;##################################
$SmtpServer = "IP"             ; address for the smtp-server to use - REQUIRED
$FromName = "Test"     ; name from who the email was sent
$FromAddress = "mail@mail.org"      ; address from where the mail should come
$ToAddress = "mail1@mail.org"            ; destination address of the email - REQUIRED
$Subject = "Error have been detected"   ; subject from the email - can be anything you want it to be
$Body = ""                              ; the messagebody from the mail - can be left blank but then you get a blank mail
$AttachFiles = "C:\Users\test\Desktop\test.xls"                       ; the file(s) you want to attach seperated with a ; (Semicolon) - leave blank if not needed
$CcAddress = ""       ; address for cc - leave blank if not needed
$BccAddress = ""     ; address for bcc - leave blank if not needed
$Importance = "Normal"                  ; Send message priority: "High", "Normal", "Low"
$Username = "????"                    ; username for the account used from where the mail gets sent - REQUIRED
$Password = "????"                  ; password for the account used from where the mail gets sent - REQUIRED
$IPPort = 25                            ; port used for sending the mail
$ssl = 0                                ; enables/disables secure socket layer sending - put to 1 if using httpS
;~ $IPPort=465                          ; GMAIL port used for sending the mail
;~ $ssl=1                               ; GMAILenables/disables secure socket layer sending - put to 1 if using httpS

;##################################
; Script
;##################################
Global $oMyRet[2]
Global $oMyError = ObjEvent("AutoIt.Error", "MyErrFunc")
$rc = _INetSmtpMailCom($SmtpServer, $FromName, $FromAddress, $ToAddress, $Subject, $Body, $AttachFiles, $CcAddress, $BccAddress, $Importance, $Username, $Password, $IPPort, $ssl)
If @error Then
    MsgBox(0, "Error sending message", "Error code:" & @error & "  Description:" & $rc)
EndIf
;
; The UDF
Func _INetSmtpMailCom($s_SmtpServer, $s_FromName, $s_FromAddress, $s_ToAddress, $s_Subject = "", $as_Body = "", $s_AttachFiles = "", $s_CcAddress = "", $s_BccAddress = "", $s_Importance="Normal", $s_Username = "", $s_Password = "", $IPPort = 25, $ssl = 0)
    Local $objEmail = ObjCreate("CDO.Message")
    $objEmail.From = '"' & $s_FromName & '" <' & $s_FromAddress & '>'
    $objEmail.To = $s_ToAddress
    Local $i_Error = 0
    Local $i_Error_desciption = ""
    If $s_CcAddress <> "" Then $objEmail.Cc = $s_CcAddress
    If $s_BccAddress <> "" Then $objEmail.Bcc = $s_BccAddress
    $objEmail.Subject = $s_Subject
    If StringInStr($as_Body, "<") And StringInStr($as_Body, ">") Then
        $objEmail.HTMLBody = $as_Body
    Else
        $objEmail.Textbody = $as_Body & @CRLF
    EndIf
    If $s_AttachFiles <> "" Then
        Local $S_Files2Attach = StringSplit($s_AttachFiles, ";")
        For $x = 1 To $S_Files2Attach[0]
            $S_Files2Attach[$x] = _PathFull($S_Files2Attach[$x])
;~          ConsoleWrite('@@ Debug : $S_Files2Attach[$x] = ' & $S_Files2Attach[$x] & @LF & '>Error code: ' & @error & @LF) ;### Debug Console
            If FileExists($S_Files2Attach[$x]) Then
                ConsoleWrite('+> File attachment added: ' & $S_Files2Attach[$x] & @LF)
                $objEmail.AddAttachment($S_Files2Attach[$x])
            Else
                ConsoleWrite('!> File not found to attach: ' & $S_Files2Attach[$x] & @LF)
                SetError(1)
                Return 0
            EndIf
        Next
    EndIf
    $objEmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
    $objEmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserver") = $s_SmtpServer
    If Number($IPPort) = 0 then $IPPort = 25
    $objEmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = $IPPort
    ;Authenticated SMTP
    If $s_Username <> "" Then
        $objEmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate") = 1
        $objEmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/sendusername") = $s_Username
        $objEmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/sendpassword") = $s_Password
    EndIf
    If $ssl Then
        $objEmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpusessl") = True
    EndIf
    ;Update settings
    $objEmail.Configuration.Fields.Update
    ; Set Email Importance
    Switch $s_Importance
        Case "High"
            $objEmail.Fields.Item ("urn:schemas:mailheader:Importance") = "High"
        Case "Normal"
            $objEmail.Fields.Item ("urn:schemas:mailheader:Importance") = "Normal"
        Case "Low"
            $objEmail.Fields.Item ("urn:schemas:mailheader:Importance") = "Low"
    EndSwitch
    $objEmail.Fields.Update
    ; Sent the Message
    $objEmail.Send
    If @error Then
        SetError(2)
        Return $oMyRet[1]
    EndIf
    $objEmail=""
EndFunc   ;==>_INetSmtpMailCom
;
;
; Com Error Handler
Func MyErrFunc()
    $HexNumber = Hex($oMyError.number, 8)
    $oMyRet[0] = $HexNumber
    $oMyRet[1] = StringStripWS($oMyError.description, 3)
    ConsoleWrite("### COM Error !  Number: " & $HexNumber & "   ScriptLine: " & $oMyError.scriptline & "   Description:" & $oMyRet[1] & @LF)
    SetError(1); something to check for when this function returns
    Return
EndFunc   ;==>MyErrFunc

EDIT: I've also tried the below code however it crashes Autoit. (I am running the script on a 64bit 2008 R2 VM

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

$smtpServer = "IP"
$fromName = "test"
$fromAddress = "noreply@mail.org"
$toAddress = "test@mail.org"
$ccAddress = ""
$subject = "Errors have been detected"
$attachment = @ScriptDir & "\test.xls"
$body = ""
$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

EDIT 2: I've noticed with this second piece of code, if I remove the attachment and CC options just to see if the script will work at all I get the following error:

C:\Users\test\Desktop\hjhjhjhjhj.au3 (155) : ==> Unknown function name.:

If _SmtpSend($v_Socket, $s_Send[0], $s_ReplyCode[0], $b_trace, "220", $s_first) Then

If ^ ERROR

Edited by kor

Share this post


Link to post
Share on other sites

Posted

Exchange means Outlook right ?

Try this:

Local $olMailItem = 0
	Local $olFormatRichText = 3
	Local $olImportanceLow = 0
	Local $olImportanceNormal = 1
	Local $olImportanceHigh = 2
	Local $olByValue = 1
	Local $olFormatHTML = 2
	Local $olFormatPlain = 1
	$oOApp = ObjCreate("Outlook.Application")
	$oOMail = $oOApp.CreateItem ($olMailItem)
	$oOMail.Save
	With $oOMail
		.To = ($to)
		.Subject = $subj
		.BodyFormat = $olFormatHTML
		.Importance = $olImportanceNormal
		.HTMLBody = "some text"
		.attachments.add ("C:\test.xls")
		.Send
	EndWith
	$oOApp=0

Share this post


Link to post
Share on other sites

Posted

I've already searched and everyone else is using the code that starts up outlook and what not. That is not they way I want to do it.

Exchange means Outlook right ?

Try this:

You didn't seem to read the first sentence of my first post. I do not want to use the code that calls outlook. Using that code requires user interaction when actually sending the email.

Share this post


Link to post
Share on other sites

Posted

That code doesnt require user interaction at all.

Maybe you have tricky outlook/OS version combination.

Share this post


Link to post
Share on other sites

Posted (edited)

I don't have outlook installed at all on the test computer. That is why I don't want to call outlook. I dont want the script dependent on if outlook is installed or not.

EDIT: tested on a computer with outlook installed just to show you. Not using your code exactly but very similar code that does pretty much does the same thing. Error below. You must not work with outlook much.

Posted Image

code I was using to test:

Local $olMailItem     = 0
    Local $olFormatRichText = 3
    Local $olImportanceLow     = 0
    Local $olImportanceNormal= 1
    Local $olImportanceHigh     = 2
Local $olByValue = 1


$oOApp = ObjCreate("Outlook.Application")
    $oOMail = $oOApp.CreateItem($olMailItem)
    ;$oOMail.Save
    With $oOMail
    .To = ("mailadres@yahoo.com")
        .Subject = "some subject"
        .BodyFormat =  $olFormatRichText
        .Importance = $olImportanceNormal
    .Body = "the body text"
      ;Display
      .Send
    EndWith
Edited by kor

Share this post


Link to post
Share on other sites

Posted

There are some outlook security settings that needs to be lowered.

And if i remember correctly some reg fixes and then you wont see that prompt.

What Outlook version do you have?

Share this post


Link to post
Share on other sites

Posted

It doesn't matter because I specifically said I don't want to use outlook in my very first sentence. I solved the issue by not trying to use AutoIt for the emailing, instead using an external program called SendEmail.exe. I lightweight smtp mailer that I just run from within Autoit. Solved.

Share this post


Link to post
Share on other sites

Posted (edited)

It doesn't matter because I specifically said I don't want to use outlook in my very first sentence. I solved the issue by not trying to use AutoIt for the emailing, instead using an external program called SendEmail.exe. I lightweight smtp mailer that I just run from within Autoit. Solved.

It should also work fine with the _INetSmtpMail() UDF which uses standard CDO. :) Edited by Jos

Share this post


Link to post
Share on other sites

Posted

But _INetSmtpMail can't add an attachment, can it?

I'm trying to do something similar. I inherited a routine from a long gone predecessor that sends mail via a VB script in Excel. Worked except for the stupid "a program is trying to send email..." thing, so I wrapped an Autoit script around it to click in all the right places. Problem solved, at the time, but the VB script is broken in Win7.

I need a way to send an email, with or without actually using Outlook, but including the Excel file attachment.

Share this post


Link to post
Share on other sites

Posted

But _INetSmtpMail can't add an attachment, can it?

Yea, I meant the _INetSmtpMailCom() which can be found in the Examples forum.

Share this post


Link to post
Share on other sites

Posted

those should works with the simple mailer using the file.au3 and the inet.au3 includes with the scripting..

without the inet.au3 the cdo mailer should still of sending the mail with the attachment only they can not made those when i tried to send of the htm file.

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