system.net.mail.attachments add error "Sorry something went wrong... " - vb.net

I'm using VB.NET and creating a new Mail outlook item using Microsoft.Interop.Outlook ver#15.
I can create an Email object and set the Subject, Body, ToAddress, ccAddress, etc. just fine and display the new Email.
I am having issues when I try and add a .pdf file via file path string to Attachments using the .Add method. Get an error "Sorry something went wrong.. " I have moved the file into different folders locally and same error.
Dim oApp As Outlook.Application = New Outlook.Application
Dim mailItem As Outlook.MailItem = oApp.CreateItem(Outlook.OlItemType.olMailItem)
mailItem.Subject = _sSubject
mailItem.To = sToAddress
mailItem.CC = sCCAddress
mailItem.Body = sBody
''Commented out for now Until I can figure out error!!
For Each _File As String In sAttachList
Dim _AttachObject As New System.Net.Mail.Attachment(_File)
mailItem.Attachments.Add(_AttachObject)
Next
mailItem.Importance = Outlook.OlImportance.olImportanceNormal
mailItem.Display(True)
mailItem = Nothing
oApp = Nothing

I think, this line is the problem:
Dim _AttachObject As New System.Net.Mail.Attachment(_File)
Why not just add the absolute file paths? So this one should do it:
For Each _File As String In sAttachList
mailItem.Attachments.Add(_File)
Next
I use this functions:
Private Function Correct(Value As String) As String
If Value = "" Then Return Value
Return Value.Trim.Replace(",", ";").Replace(" ", "")
End Function
Private Sub AddAttachments(ByRef Mail As Outlook.MailItem, Attachments As String())
If Attachments Is Nothing OrElse Attachments.Count = 0 Then Return
For Each Attachment As String In Attachments
Mail.Attachments.Add(Attachment)
Next
End Sub
Public Sub SendMail(Receiver As String,
Subject As String,
Body As String,
Optional CC As String = "",
Optional BCC As String = "",
Optional Attachments As String() = Nothing)
Receiver = Correct(Receiver)
If Receiver = "" Then Return
Dim Mail As Outlook.MailItem = CType(OUT.CreateItem(Outlook.OlItemType.olMailItem), Outlook.MailItem)
With Mail
.To = Receiver
.Subject = Subject.Trim
.Body = Body.Trim
.CC = Correct(CC)
.BCC = Correct(BCC)
AddAttachments(Mail, Attachments)
If MyAccount IsNot Nothing Then .SendUsingAccount = MyAccount
If MySentFolder IsNot Nothing Then .SaveSentMessageFolder = MySentFolder
.Send()
End With
Mail = Nothing
End Sub
These are functions in a Outlook class, so some objects need explanation:
OUT is an openend Outlook.Application object
MyAccount is an Outlook.Account object. You can use it to send the mail with another account than the default
MySentFolder is an Outlook.Folder object. You can use it, if you want to store the sent mail in another folder than the default sent folder.
Surely you can omit these two lines in the code.

Related

VBA Outlook Signature Image

I'm trying to change outlook email signatures automatically depending on a specific keyword on the subject.
On my first try I added the signature at the bottom of the email.
The signature came perfect including image and all but that there was an issue with the placement as the signature was appended at the very bottom of the email below the original text.
On my second try I set up a default signature that works as a placeholder. The macro then finds the placeholder and replaces it with the correct signature. The macro works and inserts the signature in the correct location but now the signature image is not showing up.
A couple weird things with the issue:
Image issue occurs only when composing new email. Image comes in correctly when replying or forwarding.
Signature looks okay on sender's outlook client (i.e. image is displayed before sending email).
Signature is not displayed on recipient's outlook client (tried outlook and iOS mail).
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
Dim objMail As Outlook.MailItem
Dim strSignatureFile As String
Dim objFileSystem As Object
Dim objTextStream As Object
Dim strSignature As String
Dim sPath As String
If TypeOf Item Is MailItem Then
Set objMail = Item
emailSubject = "T " & LCase(objMail.Subject)
End If
test = "keyWord"
If InStr(emailSubject, test) = 0 Then
sPath = Environ("appdata") & "\Microsoft\Signatures\signature1.htm"
signImageFolderName = "signature1_files"
Else
sPath = Environ("appdata") & "\Microsoft\Signatures\signature2.htm"
signImageFolderName = "signature2_files"
End If
completeFolderPath = Environ("appdata") & "\Microsoft\Signatures\" & signImageFolderName
If Dir(sPath) <> "" Then
strSignature = GetSignature(sPath)
' Now replace this incomplete file path
' with complete path wherever it is used
strSignature = VBA.Replace(strSignature, signImageFolderName, completeFolderPath)
Else
strSignature = ""
End If
'Insert the signature to this email
bodySignature = "<HTML><BODY><br>" & strSignature & "</br></HTML></BODY>"
objMail.HTMLBody = Replace(objMail.HTMLBody, "SingaturePlaceHolder", bodySignature)
End Sub
Function GetSignature(fPath As String) As String
Dim fso As Object
Dim TSet As Object
Set fso = CreateObject("Scripting.FileSystemObject")
Set TSet = fso.GetFile(fPath).OpenAsTextStream(1, -2)
GetSignature = TSet.readall
TSet.Close
End Function

How to choose the signature automaticaly?

I have several signatures in html format. I need to choose one of the signatures according to the domain included in To: and CC: label.
The code below merges the content of one file to the body of the mail.
There are some images in the signature file .
When I use
Set xTextStream = xFSO.OpenTextFile(xSignatureFile)
xSignature = xTextStream.ReadAll
the images aren't included in the mail.
What can I use to include images in the mail?
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
Dim xMailItem As MailItem
Dim xRecipients As Recipients
Dim xRecipient As Recipient
Dim xRcpAddress As String
Dim xSignatureFile, xSignaturePath As String
Dim xFSO As Scripting.FileSystemObject
Dim xTextStream As Scripting.TextStream
Dim xSignature As String
On Error Resume Next
Set xFSO = New Scripting.FileSystemObject
If Item.Class <> olMail Then Exit Sub
Set xMailItem = Item
Set xRecipients = xMailItem.Recipients
xSignaturePath = CreateObject("WScript.Shell").SpecialFolders(5) + "\Microsoft\Signatures\"
For Each xRecipient In xRecipients
    xRcpAddress = xRecipient.Address
    Select Case xRcpAddress
        Case "Email Address 1"
            xSignatureFile = xSignaturePath & "aaa.htm"
            Exit For
        Case "Email Address 2", "Email Address 3"
            xSignatureFile = xSignaturePath & "bbb.htm"
            Exit For
        Case "Email Address 4"
            xSignatureFile = xSignaturePath & "ccc.htm"
            Exit For
    End Select
Next
Set xTextStream = xFSO.OpenTextFile(xSignatureFile)
xSignature = xTextStream.ReadAll
xMailItem.HTMLBody = xMailItem.HTMLBody & "" & xSignature & ""
End Sub
Signatures are not exposed in the Outlook Object Model at all - it would be your responsibility to parse the HTML signature, figure out the images used, add them as attachments, set the content-id on the attachments, then modify the signature's HTML to refer to those attachment images through the content ids. You would also need to merge the HTML styles of the existing message body and the signature.
If using Redemption is an option (I am its author), it exposes the RDOSignature.ApplyTo, which would insert the given signature into a message.

Adding the default signature to Outlook email

I have an application that will fill out the To/Subject/Body of an outlook email:
Dim App As New Outlook.Application
Dim MailItem As Outlook._MailItem = DirectCast(App.CreateItem(Outlook.OlItemType.olMailItem), Outlook._MailItem)
Dim appDataDir As String = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\Microsoft\Signatures"
Dim Signature As String = String.Empty
Dim diInfo As New DirectoryInfo(appDataDir)
If diInfo.Exists Then
Dim fiSignature As FileInfo() = diInfo.GetFiles("*.htm")
If fiSignature.Length > 0 Then
Dim sr As New StreamReader(fiSignature(0).FullName, Encoding.[Default])
Signature = sr.ReadToEnd()
If Not String.IsNullOrEmpty(Signature) Then
Dim fileName As String = fiSignature(0).Name.Replace(fiSignature(0).Extension, String.Empty)
Signature = Signature.Replace(fileName & Convert.ToString("_files/"), (Convert.ToString(appDataDir & Convert.ToString("/")) & fileName) + "_files/")
End If
End If
End If
With MailItem
.To = "asdf"
.Subject = "asdf"
.Body = txtTemplatePreview.Text & vbNewLine
End With
MailItem.Display(True)
So the function of the first If Then statement is to append my default signature to the end of the email. However, when this code is run, the signature that is appended looks to be HTML code instead of the signature itself.
In addition, I'm told that the first If Then statement will fail if the user has more than one signature. Is there a way to circumvent this?
Work with HTMLBody Property
The property Returns or sets a String representing the HTML body of the specified item. The HTMLBody property should be an HTML syntax string. Read/write.
There is no need to do any of that - the signature is added automatically when Display is called if you do not set the Body or HTMLBody property before that.

How to get the sender of an outlook message

I have some code that partially populates an email message as a reply. But I can not get the sender unless they are on (an / our)? exchange server.
Public Sub CreateMessage()
Dim EmailFrom As String
Dim NewMessage As Outlook.MailItem
Dim OldMessage As Outlook.MailItem
Set OldMessage = Application.ActiveInspector.CurrentItem
Set NewMessage = Application.CreateItem(olMailItem)
EmailFrom = OldMessage.Sender.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x39FE001E")
NewMessage.Body = Body(EmailFrom)
NewMessage.HTMLBody = HTMLBody(EmailFrom)
NewMessage.Recipients.Add (EmailFrom)
NewMessage.Display
Set NewMessage = Nothing
End Sub
The message I receive is "The property "http://schemas.microsoft.com/mapi/proptag/0x39FE001E" is unknown or cannot be found." and it only appears to work with internal messages.
Anyone know of a way in Outlook VBA to get the sender of a mail message that works for all of them?
Fixed based on Dimitry's comments:
Public Sub CreateMessage()
Dim EmailFrom As String
Dim NewMessage As Outlook.MailItem
Dim OldMessage As Outlook.MailItem
Set OldMessage = Application.ActiveInspector.CurrentItem
Set NewMessage = Application.CreateItem(olMailItem)
Select Case OldMessage.SenderEmailType
Case "EX"
EmailFrom = OldMessage.Sender.GetExchangeUser.PrimarySmtpAddress
Case Else
EmailFrom = OldMessage.SenderEmailAddress
End Select
NewMessage.Body = Body(EmailFrom)
NewMessage.HTMLBody = HTMLBody(EmailFrom)
NewMessage.Recipients.Add (EmailFrom)
NewMessage.Display
Set NewMessage = Nothing
End Sub
You are requesting the PR_SMTP_ADDRESS property, which is Exchange specific. Check if SenderEmailType is "EX" and only then read the PR_SMTP_ADDRESS property. Otherwise just read the MailItem.SenderEmailAddress property.
Take a look at the message with OutlookSpy (I am its author - click IMessage) to see the available properties.

Reply body conditioned by mailbox it is sent from

So I have multiple mailboxes under my Outlook account and I am trying to get them to generate reply template based on the mailbox I am replying from (one is private, one is shared). I have tried to base the condition on SenderName and SenderEmailAddress, but to no avail (reply email gets generated with the contents of the previous email retrieved but the text I intend to put in front of it is not there; the cause is that the value of oReply.SenderEmailAddress is empty as Else clause will write the stuff as intended).
(and yes, there are snippets from code enabling reply with attachments)
Sub ReplyWithAttachments()
Dim oReply As Outlook.MailItem
Dim oItem As Object
Dim sSignature As String
Set oItem = GetCurrentItem()
If Not oItem Is Nothing Then
Set oReply = oItem.Reply
If oReply.SenderEmailAddress = "mailbox.private#something.com" Then
sSignature = "Hello and welcome!"
ElseIf oReply.SenderEmailAddress = "mailbox.shared#something.com" Then
sSignature = "Go to hell!"
End If
CopyAttachments oItem, oReply
oReply.HTMLBody = sSignature & oReply.HTMLBody
oReply.Display
oItem.UnRead = False
End If
Set oReply = Nothing
Set oItem = Nothing
End Sub
Edit:
so I managed to get somewhere with
Set oReply = oItem.Reply
sMailBox = oReply.Sender.GetExchangeUser.Address
If sMailBox = "mailbox.private#something.com" Then
sSignature = "whatever"
ElseIf sMailBox = "mailbox.shared#something.com" Then
sSignature = "bla bla bla"
Else
sSignature = "Something"
The code works as intended for the shared mailbox but for the private one, it errors out with Object variable or With block variable not set pointing to .Sender
sMailBox = oReply.Sender.GetExchangeUser.Address
I have something that I use to get sender email (as its dependent on your email exchange)
Dim strSendersEmailAddress As String
If oItem.SenderEmailType = "EX" Then
strSendersEmailAddress = oItem.Sender.GetExchangeUser.PrimarySmtpAddress
Else
strSendersEmailAddress = oItem.SenderEmailAddress
End If
You will have to get the email address before you Set oReply = oItem.Reply