Forwarding OpenPOP Attachments to SMTP (System.Net.Mail) - vb.net

I have an application I have built in Visual Studio using VB.NET that pulls mail messages from an Outlook mailbox and saves the message information into a database and downloads the attachments (if any) into a folder. Before saving the mail message to my database, if the message is from a certain user, I forward the message to another mailbox (and thus, I don't save the message). This is all working fine, except when I try to forward a message with attachments.
As stated in the title, I am using OpenPOP to pull the mail and SMTP to transfer the mail. When I try to create the SMTP attachment from the OpenPOP message I get the following error:
System.InvalidCastException: Conversion from type 'MessagePart' to type 'String' is not valid.
The message is thrown in the AddAttachments function (below) on the line:
myAttachment = New Attachment(attachment) (in the For Each statement)
Public Sub ForwardMessage(
ByVal msgPOP As OpenPop.Mime.Message,
toAddress As String,
fromAddress As String,
subject As String,
body As String
)
Dim smtpServer As New System.Net.Mail.SmtpClient(Me.serverName)
Dim msgSMTP As New MailMessage()
msgSMTP.Sender = New MailAddress(fromAddress)
msgSMTP.To.Add(New MailAddress(toAddress))
msgSMTP.Subject = subject
msgSMTP.Body = body
msgSMTP.IsBodyHtml = True
Dim attachments As Object
attachments = AddAttachments(msgPOP, msgSMTP)
msgSMTP.Attachments.Add(New Attachment(attachments))
smtpServer.Send(msgSMTP)
End Sub
I finally figured it out with some help from a friend. The AddAttachments function below has been edited to show the fix.
Public Function AddAttachments(
ByVal msgPOP As OpenPop.Mime.Message,
ByVal msgSMTP As MailMessage
) As MailMessage
Dim attachments As Object = msgPOP.FindAllAttachments()
Dim myAttachment As Attachment = Nothing
For Each attachment As OpenPop.Mime.MessagePart In attachments
Dim sName As String = attachment.FileName
Dim sContentType As String = attachment.ContentType.MediaType
Dim stream As MemoryStream = New MemoryStream(attachment.Body)
myAttachment = New Attachment(stream, sName, sContentType)
msgSMTP.Attachments.Add(myAttachment)
Next
Return msgSMTP
End Function
I have spent hours researching this issue and I have not found one solution yet. I tried changing the application data type to String and OpenPOP.MIME.MessagePart to no avail. I tried adding "ToString" to the attachment variable and received the following error:
System.InvalidCaseException: Operator '&' is not defined for type 'MessagePart' and string ".ToString".
I have been reading up on MIME to see if that would offer some ideas, though I have not been able to connect the dots. I am assuming this is possible and hoping someone will be able to share the solution, and I will be happy with either VB.NET or C#.NET.
Thank you very much in advance and I appreciate your time.

The solution is in the edited AddAttachments function in my original post above.

Related

Microsoft Graph SendMail returns ErrorInternalServerError

I'm writing a program to send internal emails in VB.Net using the official Microsoft Graph package. At first I got it to send calendar invites and that worked fine for months, but when I tried to add the ability to send emails I keep getting an Internal Server Error.
From looking at other times people have got this error from Graph, it appears to be when a malformed request is sent or when values that don't quite make sense are given. I'm using the constructors from the package and using basically the same construction method as every example online, so the structure of the request can't be wrong, and the only fields that I'm using just take text and don't do anything with it, so I don't think that can be the issue either.
I have the correct permissions in Azure: Screenshot of permissions in Azure, including Mail.Send
Here's my code for constructing the email:
Function DefineImportantEmail(Locations As String, Recipients As List(Of (String, String))) As Message
Dim title = "IMPORTANT OUTAGE NOTIFICATION"
Dim message = "Outage at " & Locations
Dim RecipientList = New List(Of Recipient)
For Each recipient In Recipients
RecipientList.Add(New Attendee With {
.EmailAddress = New EmailAddress With {
.Address = recipient.Item1,
.Name = recipient.Item2
},
.Type = AttendeeType.Optional
})
Next
Return New Message With {
.Subject = title,
.Body = New ItemBody With {
.ContentType = BodyType.Text,
.Content = message
},
.ToRecipients = RecipientList
}
End Function
And here's the code I use to send the email:
Sub SendImportantEmail(Locations As String, Recipients As List(Of (String, String)))
Dim SaveToSentItems = True
Dim graphClient = GetGraphClient()
Dim EventObject = DefineImportantEmail(Locations, Recipients)
Dim request = graphClient.Users("xxxxx#xxxxxxxxxxxxxxx.com").SendMail(EventObject, SaveToSentItems).Request().PostAsync()
request.Wait()
End Sub
The GetGraphClient function works for any other API endpoint I've tried, so I haven't included it. The censored user is from our organisation and is also the user I sent calendar invites from in the first version of this program.
Here's the full error message I get:
(Code: ErrorInternalServerError
Message: An internal server error occurred. The operation failed.
ClientRequestId: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
)
---> Status Code: InternalServerError
Microsoft.Graph.ServiceException: Code: ErrorInternalServerError
Message: An internal server error occurred. The operation failed.
ClientRequestId: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

How can I program Outlook to send an email in advance and send another if a reply isn't sent?

I'd like to program Outlook to send an email in advance, and, if no reply is sent to the target email by x date, send another email.
I've attempted experimentation, dabbling into Excel VBAs, but haven't found a solution.
I'm really quite unsure of how to do this, though I do have programming experience.
I'd like to program Outlook to send an email in advance
That is a very straightforward task. A lot of samples are available over the internet, for example, sample code in VB.NET:
Private Sub CreateSendItem(OutlookApp As Outlook._Application)
Dim mail As Outlook.MailItem = Nothing
Dim mailRecipients As Outlook.Recipients = Nothing
Dim mailRecipient As Outlook.Recipient = Nothing
Try
mail = OutlookApp.CreateItem(Outlook.OlItemType.olMailItem)
mail.Subject = "A programatically generated e-mail"
mailRecipients = mail.Recipients
mailRecipient = mailRecipients.Add("Eugene Astafiev")
mailRecipient.Resolve()
If (mailRecipient.Resolved) Then
mail.Send()
Else
System.Windows.Forms.MessageBox.Show(
"There is no such record in your address book.")
End If
Catch ex As Exception
System.Windows.Forms.MessageBox.Show(ex.Message,
"An exception is occured in the code of add-in.")
Finally
If Not IsNothing(mailRecipient) Then Marshal.ReleaseComObject(mailRecipient)
If Not IsNothing(mailRecipients) Then Marshal.ReleaseComObject(mailRecipients)
If Not IsNothing(mail) Then Marshal.ReleaseComObject(mail)
End Try
End Sub
Read more about that in the following articles:
How To: Create and send an Outlook message programmatically
How To: Fill TO,CC and BCC fields in Outlook programmatically
How to create and show a new Outlook mail item programmatically: C#, VB.NET
if no reply is sent to the target email by x date, send another email.
You can set the following properties on the email:
MailItem.TaskDueDate which sets a Date value that represents the due date of the task for this MailItem.
MailItem.ReminderSet which sets a Boolean value that is True if a reminder has been set for this item.
MailItem.ReminderTime which sets a Date indicating the date and time at which the reminder should occur for the specified item.
In the Application.Reminder event handler you may check whether the mail item was replied or forwarded by reading a low-level property value. The property you would read would be PR_LAST_VERB_EXECUTED (0x10810003). Values are listed below:
EXCHIVERB_REPLYTOSENDER = 102
EXCHIVERB_REPLYTOALL = 103
EXCHIVERB_FORWARD = 104
Please remember that you can use the PropertyAccessor for that:
lastVerbExecuted = mailItem.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x10810003")

VBA Outlook script error: an object could not be found

I am trying to use a VBA script to pull info from the emails in Inbox into an excel spreadsheet:
'Subject
'To Address
'From Address
'CC Addresses
it fails for senders who have already left the organization and they're no longer in O365.
This is the code bit:
Function X400toSMTP(strAdr As String) As String
Dim olkRcp As Outlook.Recipient, olkUsr As Outlook.ExchangeUser
Set olkRcp = Session.CreateRecipient(strAdr)
If olkRcp.AddressEntry = Empty Then
X400toSMTP = strAdr
ElseIf olkRcp.AddressEntry.AddressEntryUserType = olExchangeUserAddressEntry Then
olkRcp.Resolve
Set olkUsr = olkRcp.AddressEntry.GetExchangeUser
X400toSMTP = olkUsr.PrimarySmtpAddress
End If
Set olkRcp = Nothing
Set olkUsr = Nothing
End Function
I ran the debug and it stops at AddressEntry : The attempted operation failed. An object could not be found
I'm trying to find a way to make the script leave the address field empty for those senders who cannot be found on O365 anymore and further process the rest of the items in the Inbox.
I have tried the below:
If IsNull(olkRcp.AddressEntry) Then
X400toSMTP = strAdr
but am still getting the same error for AddressEntry.
I am just a VBA noob so would very much appreciate your advice.
Many thanks!
Make sure the recipient is resolved before accessing the AddressEntry property - call olkRcp.Resolve.

Read the first mail in the inbox, save subject content as a text file using pop3client

Am facing a problem while saving the mail as a text file through vb.net. i had done the following code as per my task:-
public sub rearmail()
Dim pop3Client As Pop3Client
If (Session("Pop3Client") Is Nothing) Then
pop3Client = New Pop3Client
pop3Client.Connect("pop.gmail.com", 995, True)
pop3Client.Authenticate("mymail#gmail.com", "password")
Session("Pop3Client") = pop3Client
Else
pop3Client = CType(Session("Pop3Client"), Pop3Client)
End If 'connect to the inbox with username and pass word authentication
Dim message As Message = pop3Client.GetMessage(0)
dim frm as string ' to store from address
dim subj as string ' to store the subject
dim mdate as date ' to store the date and time
frm=message.Headers.From.Address
subj= message.Headers.Subject
mdate=message.Headers.DateSent
'**** no i need to read the mail message and save it as a notepad file ****
end sub
i had tried a lot to read the mail using :-
Dim message As Message = pop3Client.GetMessage(0)
as follows:-
Dim str As MailMessageEventArgs
dim strmsg as string
strmsg=str..Message.Body.ToString 'error null error exception at run time
strmsg=message.MessagePart.Body ' nothing will return
like wise i do a lot with the message object but i fails to achieve the goal, i hope that the experts in this community can help me to overcome the problem,
thanks in advance.....♥
thanks for the one who make a try to solve the problem, i got the solution now i wish to share it with you. here is the code segment to read the mail body content;-
Dim messagePart As MessagePart = message.MessagePart.MessageParts(0)
MsgBox(messagePart.BodyEncoding.GetString(messagePart.Body))

ususual problem with system.net.mail attachment

I have an ususual problem with my attachment memorystream on a VB.net project. I am calling a shared member (SendMail) passing in a customer object and a memorystream of a file to be sent as an attachment. Within the "SendMail" it calls two separate functions to prepare one regular email and another for a digitally signed email. The problem I have is I recieve the digitally signed email perfect, however, in the regular email, the attachment is blank and the file name has appended (64 B). If I disable the part of the digitally signing the regular mails works fine. It looks like somewhere the memorystream is changed in the digital signing.
Here his how I make the calls
mailHelper.SendMail(cust, attachment)
withing the mailHelper CLASS
Public Shared Sub SendEmail(ByVal cust As Customer, ByVal attachment As MemoryStream)
Dim messages As New List(Of MailMessage)
messages.Add(CreateUnSignedMail(cust,attachment)
messages.Add(CreateSignedMail(cust,attachment)
SendSMTPMail(messages)
End Sub
Private Shared Function CreateUnSignedMail(ByVal cust As Customer, ByVal attachment As MemoryStream) As MailMessage
Dim eMail As New MailMessage()
With eMail
.//Normal properties set (like to, from etc)
.Attachments.Add(New Attachment(attachment, "someFilename.doc")
End With
Return eMail
End Function
Private Shared Function CreateSignedMail(ByVal cust As Customer, ByVal attachment As MemoryStream) As MailMessage
Dim eMail As New SecureMailMessage()
With eMail
.//Normal properties set (like to, from etc)
.Attachments.Add(New SecureAttachment(attachment, "someFilename.doc")
End With
Return eMail
End Function
Private Shared Sub SendSMTPMail(ByVal messages As List(Of System.Net.Mail.MailMessage))
Dim smtp As New SmtpClient("myServer")
Try
With smtp
.//Additional properties set
For Each email In messages
.Send(email)
Next
End With
Catch ex As Exception
//Log error to file.
Logger.Log.Error("SMTP Error", ex)
Throw
End Try
End Sub
If I try the following it works fine, however, is this the proper solution?
messages.Add(SendUnSignedMail(cust, New MemoryStream(attachment.ToArray())))
messages.Add(SendSignedMail(cust, New MemoryStream(attachment.ToArray())))
Assume you already fixed this given the delay in getting an answer but here is my attempt anyhow...
There are quite a few overloads to create an Attachment, none of them match the way you initialised the Attachment.
When creating an Attachment the second parameter needs to be either NULL or identify a valid MIME-type for your attachment.
Hope this helps.