Outlook Rule Save email to text - vba

I'm having trouble with automatically exporting the body of an email into a text file using a script.
I've managed a script that will save the text into a file on a macro but that won't work on a rule which is what I need.
My current code is as follows:
Sub SaveAsTXT()
Dim myItem As Outlook.Inspector
Dim objItem As Object
Dim myFolder As Folder
Set myItem = Application.ActiveInspector
If Not TypeName(myItem) = "Nothing" Then
Set myNamespace = Application.GetNamespace("MAPI")
Set myFolder = myNamespace.GetDefaultFolder(olFolderInbox)
Set objItem = myItem.CurrentItem
strname = objItem.Subject
strdate = Format(objItem.ReceivedTime, " yyyy mm dd")
objItem.SaveAs "c:\users\philip\documents\" & strname & strdate & ".txt", olTXT
End If
End Sub
Apologies if it looks a bit messy, I've edited it countless times trying to get it to work.
That's the code that will correctly run when I'm in the open email and run it as a macro but it won't work correctly when run as a rule
I have tried amending to Sub SaveAsTXT(Item as Outlook.Mailitem) but this also doesn't seem to work
So basically the question is how to I ensure the code will select the email (which will always be entitled "Rotas" without quotes) when it is run as a rule?
Info: Using office 2010 and I'm not a very good coder to start with.

Actually I managed to sort it out myself.
I didn't consider that the item as Outlook.Mailitem element was actually the thing that was selected by the rule. So I applied item as the object rather than objItem
Find the successful (and cleaned up) code below:
Sub SaveAsTXT(myMail As Outlook.MailItem)
Dim objItem As Object
Dim myFolder As Folder
If Not TypeName(myitem) = "Nothing" Then
If myMail.Subject = "Rotas" Then
strname = myMail.Subject
strdate = Format(myMail.ReceivedTime, " yyyy mm dd")
myMail.SaveAs "c:\users\philip\documents\" & strname & ".txt", olTXT
End If
End If
End Sub

Related

Save all Outlook mailitems to disk with VBA

I have some experience with VBA in Excel, but taking my first steps in Outlook. I need to save all e-mail messages in a designated Outlook folder (Inbox\input) to disk (D:\myArchive\Email\) as .msg files and move mail item to archive folder in Outlook (Inbox\archive).
I have set up a mail rule in Outlook that moves mail to archive folder and runs a script below which actually does what I need. The problem is that I get mail rule error pop-ups occasionally and I struggle to track down the reason. Hence looking to turn away from Outlook mail rule and cycle through all folder contents "on-demand".
How could I convert it to cycle through Outlook folder as well as displace the mail item? Currently running Outlook 2019. Thanks!
edit: sorry, late clarification - target folder is in another mailbox (Office 365 shared mailbox). How to target a different account?
Public Sub saveEmailtoDisk(itm As Outlook.MailItem)
Dim saveFolder, msgName1, msgName2 As String
saveFolder = "D:\myArchive\Email\"
msgName1 = Replace(itm.Subject, ":", "")
msgName2 = Replace(msgName1, "/", "_")
itm.SaveAs saveFolder & msgName2 & ".msg", olMSG
End Sub
The following code assumes that both the input and archive folders are located within the default inbox.
Public Sub saveAndArchiveInputEmails()
Dim saveFolder As String
saveFolder = "D:\myArchive\Email\"
Dim sourceFolder As Folder
Dim destFolder As Folder
With Application.GetNamespace("MAPI").GetDefaultFolder(olFolderInbox)
Set sourceFolder = .Folders("input")
Set destFolder = .Folders("archive")
End With
Dim itm As Object
Dim i As Long
With sourceFolder
For i = .Items.Count To 1 Step -1
Set itm = .Items(i)
If TypeName(itm) = "MailItem" Then
saveEmailtoDisk saveFolder, itm
itm.Move destFolder
End If
Next i
End With
End Sub
Public Sub saveEmailtoDisk(ByRef saveFolder As String, ByVal itm As Object)
Dim msgName1, msgName2 As String
msgName1 = Replace(itm.Subject, ":", "")
msgName2 = Replace(msgName1, "/", "_")
itm.SaveAs saveFolder & msgName2 & ".msg", olMSG
End Sub
EDIT
For a shared mailbox, try the following instead...
With Application.GetNamespace("MAPI")
Dim sharedEmail As Recipient
Set sharedEmail = .CreateRecipient("someone#abc.com")
Dim sourceFolder As Folder
Set sourceFolder = .GetSharedDefaultFolder(sharedEmail, olFolderInbox).Folders("input")
Dim destFolder As Folder
Set destFolder = .GetSharedDefaultFolder(sharedEmail, olFolderInbox).Folders("archive")
End With
For your default inbox...
Dim myInbox As Folder
Set myInbox = Application.GetNamespace("MAPI").GetDefaultFolder(olFolderInbox)

Outlook Corrupts PDF When SaveAsFile Used

I'm using the following code to automatically export PDF files in Outlook when they arrive in my inbox. However the file that it saves is corrupted. The SaveAsFile method only takes one argument - the file path to save to - it doesn't say in the documentation that I can pass a filetype. How do I save these PDF attachments without corrupting the files?
Private WithEvents Items As Outlook.Items
Private Sub Application_Startup()
'Declaring Variables [BD]
Dim oOutlook As Outlook.Application
Dim oNameSpace As Outlook.NameSpace
Dim oFolder As Outlook.MAPIFolder
'Intializing Variables [BD]
Set oOutlook = Outlook.Application
Set oNameSpace = Application.GetNamespace("MAPI")
Set oFolder = oNameSpace.GetDefaultFolder(olFolderInbox).Parent
Set oFolder = oFolder.Folders("Produce Availability").Folders("Earls Organic")
Set Items = oFolder.Items
End Sub
Private Sub Items_ItemAdd(ByVal Item As Object)
'Declaring Variables [BD]
Dim sOutputFileName As String
Dim oMessage As Outlook.MailItem
Dim oAttachment As Outlook.Attachments
'Initializing Variables [BD]
sDateTime = Format(Now(), "yyyymmddhhnnss")
sOutputFolderPath = "C:\Earls Organic\"
On Error GoTo ErrorHandler
If TypeName(Item) = "MailItem" Then
Set oMessage = Item
Set oAttachment = oMessage.Attachments
sOutputFileName = oMessage.Subject & " " & sDateTime
sOutputFolderPathAndName = sOutputFolderPath & sOutputFileName & ".pdf"
oAttachment.Item(1).SaveAsFile sOutputFolderPathAndName
Set oAttachment = Nothing
Set oItem = Nothing
End If
ProgramExit:
Exit Sub
ErrorHandler:
MsgBox Err.Number & " - " & Err.Description
Resume ProgramExit
End Sub
As requested, here is my comment as an answer:
Are you sure Attachment(1) is the PDF file? Signatures and images can be recorded as attachments. You should scan down the attachment collection checking the extension until you find the PDF file.
SaveAsFile does not corrupt files. You never check that the file is actually a PDF - you can have other attachments which may or may not be seen as such in Outlook (such as images). You assume that the very first attachment is a PDF. Loop through all attachments do check the Attachment.FileName property to make sure you get what you expect.

Save email attachment based on email subject

Ever day at 12 am there is an automatic email with an excel attachment from a vendor service with a specific subject. I am using rules and code to attempt to save the attachment and insert the information into a database I have created upon being received in the inbox.
I have tried code that I have found online however I don't know if doesn't work because of some network/ security setting my company has or if its he code it self.
Rule:
CODE:
Public Sub CribMaster2Database(itm As Outlook.MailItem)
Dim objAtt As Outlook.Attachment
Dim saveFolder As String
saveFolder = "c:\temp\"
If olItem.Subject = "Test" Then
For Each objAtt In itm.Attachments
objAtt.SaveAsFile saveFolder & "\" & objAtt.DisplayName
Set objAtt = Nothing
Next
End If
End Sub
Add code to the ThisOutlookSession to watch your folder for arrivals.
CribMaster_ItemAdd fires whenever something arrives in your watched folder.
At the very top of the module:
Dim WithEvents CribMaster As Items
Const SAVE_PATH As String = "c:\temp\"
Private Sub Application_Startup()
Dim ns As Outlook.NameSpace
Set ns = GetNamespace("MAPI")
'Change `holi4683` to the name of your account
'(should be visible just above your inbox).
Set CribMaster = ns.Folders.Item("holi4683") _
.Folders.Item("Inbox").Items
End Sub
Sub CribMaster_ItemAdd(ByVal Item As Object)
Dim olAtt As Attachment
Dim i As Integer
With Item
For i = 1 To .Attachments.Count
Set olAtt = .Attachments(i)
olAtt.SaveAsFile SAVE_PATH & olAtt.DisplayName
.UnRead = False
DoEvents
Next i
End With
Set olAtt = Nothing
End Sub
I'd usually use a rule to move the emails to a subfolder and watch that folder - means I don't have to worry about meeting invites, etc.
To do this you'd change your watched folder like this:
Set CribMaster = ns.Folders.Item("holi4683") _
.Folders.Item("Inbox") _
.Folders.Item("SubFolder").Items
Restart Outlook for the code to work, or manually run the Application_Startup() procedure.

Save outlook attachments and rename/append files with identifier from subject line

Im really new to VBA and need some help. I'm trying to write a VBA script (along with a Outlook rule) to automatically download attachments from daily emails and append the file names with the date that appears in the subject.
This is what the subject line looks like - "Email Alert for Department for 10/20/2014". I just need to isolate the rightmost 10 spaces that indicates the run date of the files.
So I found code online that works to automatically download the attachments and append by current date which does work. See below.
Public Sub saveAttachtoDisk(itm As Outlook.MailItem)
Dim objAtt As Outlook.Attachment
Dim saveFolder As String
Dim dateFormat
dateFormat = Format(Now, "yyyymmdd ")
saveFolder = "Z:\Daily Emails"
For Each objAtt In itm.Attachments
objAtt.SaveAsFile saveFolder & "\" & dateFormat & objAtt.DisplayName
Set objAtt = Nothing
Next
End Sub
I also found online that something like this should point to the date (formatted like XX/XX/XXXX and always at the end of the subject line.
Subject = Right(itm.Subject, 10) but im having trouble incorporating it into the code above.
Can anyone help me? It would mean a lot
Thanks!
-Christina
Using Rules to run a macro is good.
I used the same set up before. The problem is if you are to work on the newly received mail, the sub wouldn't trap it. If you need to save the attachment of an incoming email with Email Alert for Department for mm/dd/yyyy as subject, try using an event instead. By default, Outlook doesn't provide Items Event so you'll have to create it.
In your ThisOutlookSession (not in a module) try something like:
Option Explicit
Private WithEvents olIBoxItem As Outlook.Items
Private Sub Application_Startup()
Dim olApp As Outlook.Application
Dim objNS As Outlook.NameSpace
Dim olFolder As Outlook.MAPIFolder
Set olApp = Outlook.Application
Set objNS = olApp.GetNamespace("MAPI")
Set olFolder = objNS.GetDefaultFolder(olFolderInbox)
'~~> change olFolder depending on what folder you're receiving the email
'~~> I assumed it is Outlook's default folder Inbox
Set olIBoxItem = olFolder.Items
End Sub
Private Sub olIBoxItem_ItemAdd(ByVal Item As Object)
Const strSub As String = "Email Alert for Department for "
If TypeOf Item Is Outlook.MailItem Then
Dim nMail As Outlook.MailItem
Set nMail = Item
If InStr(nMail.Subject, strSub) <> 0 Then
Const savefolder As String = "Z:\Details Mail\"
'~~> Extract your date
Dim dateSub As String: dateSub = Right(nMail.Subject, 10)
'~~> Make sure there is an attachment
If nMail.Attachments.Count > 0 Then
Dim olAtt As Outlook.Attachment
Set olAtt = nMail.Attachments.Item(1) '~~> if you only have 1
Dim attFName As String, addFExt As String
'~~> Get the filename and extension separately
attFName = Split(olAtt.Filename, ".")(0)
attFExt = Split(olAtt.Filename, ".")(1)
'~~> Reconstruct the filename
attFName = savefolder & attFName & " " & dateSub & attFExt
'~~> Save the attachment
olAtt.SaveAsFile attFName
End If
End If
End If
End Sub
So above routine automatically checks any received mail in the Inbox Folder. If the subject contains the specified string. If yes, it automatically saves the attachment.
If however you have more than one attachment, you'll have to look through it and then save each one. It may look confusing at first but you'll get the hang of it for sure. HTH.

VBA retrieve HTMLBody from Outlook mail

First I create an email via Outlook:
Sub CreateHTMLMail()
'Creates a new e-mail item and modifies its properties.
Dim olApp As Outlook.Application
Dim objMail As Outlook.MailItem
Set olApp = Outlook.Application
'Create e-mail item
Set objMail = olApp.CreateItem(olMailItem)
Dim sHTML_Open As String
Dim sHTML_Introduction As String
Dim sHTML_Goodbye As String
Dim sHTML_Close As String
Dim sHTML_Process_Date As String
Dim sHTML_Processor As String
Dim sHTML_Issuer As String
Dim sHTML_Details As String
Dim sHTML_Body As String
sHTML_Open = "<HTML><BODY>"
sHTML_Introduction = "Hi team,<BR/><BR/>" & _
"Data is ready to process. Please find details as below.<BR/>"
sHTML_Process_Date = "<P ID='PROCESSDATE'>28 February 2013</P>"
sHTML_Processor = "<P ID='PROCESSOR'>AKSHAY</ID></P>"
sHTML_Issuer = "<P ID='ISSUER'>DATAGROUP.COM</ID></P>"
sHTML_Details = "<P ID='DETAILS'>" & _
"<UL>" & _
"<LI>Fimta23456 09:00:00 flor345</LI>" & _
"<LI>Fimta23456 09:00:00 flor345</LI>" & _
"</UL>" & _
"</P><BR/>"
sHTML_Goodbye = "Thanks"
sHTML_Close = "</BODY></HTML>"
sHTML_Body = sHTML_Open & sHTML_Introduction & sHTML_Process_Date & sHTML_Processor & sHTML_Issuer & _
sHTML_Details & sHTML_Goodbye & sHTML_Close
With objMail
'Set body format to HTML
.BodyFormat = olFormatHTML
.To = "Kim Gysen"
.Subject = "data remit file"
.HTMLBody = sHTML_Body
.Display
End With
End Sub
Via code, I want to retrieve values based on ID.
This seemed the cleanest way for me, I don't particulary like the "split" method because it's kind of hard coding; not very dynamic and kinda unreliable.
Unfortunately when I retrieve the HTML body, I cannot retrieve the original HTML, as it is distorted by Outlook:
Sub Get_OL()
Dim oFolder As MAPIFolder
Dim oItem As Variant
Dim sHTML_Body As String
Dim sHTML_Process_Date As String
Dim sHTML_Processor As String
Dim sHTML_Issuer As String
Dim sHTML_Details As String
Dim oExcel As Object
Dim oBook As Workbook
Set oExcel = CreateObject("Excel.Application")
Set oBook = oExcel.Workbooks.Add
'Access the outlook inbox folder
Set oFolder = GetNamespace("MAPI").PickFolder
'On error resume next usually not to use, but feteching emails may give unexpected errors
On Error Resume Next
For Each oItem In oFolder.Items
If TypeOf oItem Is Outlook.MailItem Then
If oItem.Subject Like "*data remit file*" Then
'Turn off on error resume next asap
On Error GoTo 0
sHTML_Body = oItem.HTMLBody
Debug.Print sHTML_Body
Exit For
End If
End If
Next oItem
End Sub
On debug.print, this is what I get (only putting the last line of the Format):
</o:shapelayout></xml><![endif]--></head><body lang=EN-GB link=blue vlink=purple><div class=WordSection1><p class=MsoNormal>Hi team,<br><br>Data is ready to process. Please find details as below.<br><br><o:p></o:p></p><p>28 February 2013<o:p></o:p></p><p id=PROCESSOR>AKSHAY<o:p></o:p></p><p id=ISSUER>DATAGROUP.COM<o:p></o:p></p><ul type=disc><li class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;mso-list:l0 level1 lfo1'>Fimta23456 09:00:00 flor345<o:p></o:p></li><li class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;mso-list:l0 level1 lfo1'>Fimta23456 09:00:00 flor345<o:p></o:p></li></ul><p class=MsoNormal><br>Thanks<o:p></o:p></p></div></body></html>
I would like to retrieve the original HTML that I put in the HTMLBody.
2 ways:
1) parsing text - several things to do (not recommended: hard-coding)
All what you need is to parse text, but MSDN shows how to do it using InStr function. I would strongly suggest to use RegEx to parse html text. Note: reference to MS VBScript Regular Expressions x.x is needed.
Simple Regular Expression Tutorial for Excel VBA
2) using UserProperites of MailItem object (recommended)
If MailItem doesn't contains your propert(y)ies, than there is nothing to do ;)
How to: Add custom property