Казалось бы простейшая задача - папка "Входящие" в которую валится почта.
В папке - подпапка клиенты, в ней - еще подпапки с номерами клиентов типа: 102345, 102201 и тп.
Надо написать скрипт, который смотрит тему письма, и какой там номер встречается - в такую папку перемещаем сообщение из "входящих".
Перерыл кучу всего, почему то не выходит.
Не срабатывает на событие "Получение почты", точнее NewItem in Inbox.
Что-то я не так делаю.
И еще вопрос - я пытался віполнить пошагово кучу макросов, ставил точки для стопов - оно нигде не останавливалось.
Как вообще под этот Аутлук пишут то?
Мои попытки :
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
346.
347.
348.
349.
350.
351.
352.
353.
354.
355.
356.
357.
358.
359.
360.
361.
362.
363.
364.
365.
366.
367.
368.
369.
370.
371.
372.
373.
374.
375.
376.
377.
378.
379.
380.
381.
382.
383.
Private WithEvents olInboxItems As Items
Private WithEvents olSentItems As Items
Private WithEvents olDeletedItems As Items
Dim SavedPath As String
Private Const BUSINESS_FOLDER = "clients"
' Bugfix #9
Dim objNameSpace As Outlook.NameSpace
Dim objStore As Outlook.Store
' Some basic variables
Dim strFolderName As String
Dim strHits As String
' Register our event hooks.
Private Sub Application_Startup()
Dim NS As Outlook.NameSpace
' ALEX: add 08-12-16
Set oInspectors = Application.Inspectors
Set NS = Application.GetNamespace("MAPI")
Set olInboxItems = Session.GetDefaultFolder(olFolderInbox).Items
Set olSentItems = Session.GetDefaultFolder(olFolderSentMail).Items
'Set olDeletedItems = NS.GetDefaultFolder(olFolderDeletedItems).Items
Set NS = Nothing
End Sub
' This section manages incoming emails.
Private Sub olInboxItems_ItemAdd(ByVal item As Object)
' If the item type is a mailitem (email)
If TypeOf item Is MailItem Then
' Validate the email
ValidateEmail item
End If
End Sub
' This section manages outgoing (sent) emails.
' Note: This is only triggered when the email is placed in Sent Items.
' Emails in outbox, that have not yet been sent, will not be detected.
Private Sub olSentItems_ItemAdd(ByVal item As Object)
If TypeOf item Is MailItem Then
ValidateEmail item
End If
End Sub
' ALEX: START block comment 08-12-16
' This section manages deleted items.
'Private Sub olDeletedItems_ItemAdd(ByVal item As Object)
' If TypeOf item Is MailItem Then
' validateEmail item
' End If
'End Sub
' ALEX: END
' This function manages the criteria processing of our items.
'
Private Function ValidateEmail(ByVal item As Object)
' The error handler here will avoid the application hanging / terminating unexpectedly.
On Error GoTo cannotValidate
' Prepare outside variables
Dim olMailItem As MailItem
' Store the item (email passed to this function)
Set olMailItem = item
' Check criteria
If UCase(olMailItem.Subject) Like UCase("*CB??????*") = True Or UCase(olMailItem.Body) Like _
UCase("*CB??????*") = True Then
' Prepare the rest of our variables, to save on memory footprint.
Dim objOutlook As Outlook.Application
' Dim objNameSpace As Outlook.NameSpace
Dim objSourceFolder As Outlook.MAPIFolder
Dim objDestFolder As Outlook.MAPIFolder
Dim strCriteria As String
' Store received criteria
If UCase(olMailItem.Subject) Like UCase("*CB??????*") = True Then
strCriteria = Mid(olMailItem.Subject, InStr(UCase(olMailItem.Subject), "CB"), 8)
ElseIf UCase(olMailItem.Body) Like UCase("*CB??????*") = True Then
strCriteria = Mid(olMailItem.Body, InStr(UCase(olMailItem.Body), "CB"), 8)
End If
' Set the value of our scope variables.
Set objOutlook = Application
' Buxfix #9 - Bind NameSpace relative to MailItem.
Set objNameSpace = olMailItem.Session
Set objStore = olMailItem.Parent.Store
Set objSourceFolder = objNameSpace.GetDefaultFolder(olFolderInbox)
' This is where the initial magic of this macro runs.
' Note: This macro searches all folders that begin with the criteria passed.
Set objDestFolder = GetFolder(getDestinationFolder(strCriteria))
' Check that the final destination variable is now saved.
' WIP - Want to set this as a 'nothing' value, and compare against 'if not objDestFolder isnothing' then.
' Obviously; If this criteria is not met, the macro did not find a destination folder, and then will skip it.
If Not objDestFolder Is Nothing Then
olMailItem.Move objDestFolder
End If
' Clear the variables defined in this scope.
Set objOutlook = Nothing
Set objNameSpace = Nothing
Set objSourceFolder = Nothing
Set objDestFolder = Nothing
End If
' Clear our remaining variable
Set olMailItem = Nothing
cannotValidate:
' Take no action - this prevents unhandled exceptions or the macro crashing.
End Function
' This function searches for the destination folder that meets the criteria of getFolderName (passed) string.
Private Function getDestinationFolder(getFolderName As String)
' Error handling
On Error GoTo failedGetDestinationFolder
strFolderName = getFolderName
' Prepare our variables
Dim olkStore As Outlook.Store
Dim olkRoot As Outlook.folder
Dim olkSearchFolder As Outlook.folder
' STR Hits is used to confirm if we have a hit on a folder search for each search - rather
' than being saved once for entire app.
strHits = ""
' Check if saved path is stored.
' Note: That SavedPath is stored the first time any email is processed successfully
' (That is, criteria is met, folder is found, and email is stored).
' This was created to stop performance impacts when an email was processed in a
' mailbox that had hundreds of emails. Instead, now, a relative parent_
' path is stored, and subsiquent searches begin from this SavedPath location.
' Additionally: We can manage this feature moving forward, allowing it to search that location first, and
' then search the whole mailbox if not found.
' For the current feature request of DOBG - the 'clients' folder is the only folder we are to search.
If SavedPath = "" Then
' Literally: For each mailbox (account)
For Each olkStore In objNameSpace.Stores
If strHits = "" Then
' Set this as our current outlook root variable
Set olkRoot = olkStore.GetRootFolder
' For each folder within this root store's
For Each olkSearchFolder In olkRoot.Folders
' Force the application to stop searching again, and again.
If strHits = "" Then
' If the folder name is CLIENTS
If UCase(olkSearchFolder.Name) = "CLIENTS" Then
' Foreach sub folder of the clients folder.
For Each olkSearchFSubolder In olkSearchFolder.Folders
' Added here to stop processing folders once the hit is found - given we are using a 'for each'
If strHits = "" Then
' Process that folder
ProcessFolder olkSearchFolder
End If
Next
End If
End If
Next
End If
Next
' Else: A saved path DOES exist. Lets begin our searches from that location instead.
Else
' Set our outlook root as the SavedPath variable
Set olkRoot = GetFolder(SavedPath)
' For each folder in that saved path
For Each olkSearchFolder In olkRoot.Folders
' Process the folder.
ProcessFolder olkSearchFolder
Next
End If
' If there are no hits by this stage, the criteria was met - but the destination folder was not found.
If strHits = "" Then
' Return (string) NULL
' Note: I want to change this to setting the result to the vb value nothing.
getDestinationFolder = "NULL"
' Else
Else
' The folder WAS found, return the destination folder.
getDestinationFolder = strHits
Exit Function
End If
' Unset the variables used in this function.
Set olkRoot = Nothing
Set olkStore = Nothing
Set olkSearchFolder = Nothing
failedGetDestinationFolder:
' Avoids unexpected application hang / termination.
Exit Function
End Function
' Process the actual folder. This uses an environment (not scope) variable for comparison - avoiding us having to pass this variable each function. Perhaps not ideal?
Sub ProcessFolder(olkFld As Outlook.folder)
' Error handling
On Error GoTo failedProcessingFolder
' If the folder matches our required criteria (The first 8 characters, in upper case, match the folder name we are looking for (also in upper case))
'If UCase(olMailItem.Subject) Like UCase("*CB??????*") = True Then
If UCase(olkFld.Name) Like UCase("*" & strFolderName & "*") = True Then
' Set our strHits to a hit.
strHits = olkFld.FolderPath
' Save a relative (In this case, first level - parent) path.
SavedPath = olkFld.Parent.FolderPath
' Else
Else
' Prepare some space for each of the sub folders of this folder.
Dim olkSub As Outlook.folder
' For each sub folder at this level.
For Each olkSub In olkFld.Folders
' Process (sub function) that folder.
ProcessSubFolder olkSub
Next
' Clear our function variable
Set olkSub = Nothing
End If
failedProcessingFolder:
'
End Sub
' =====================================
' ALEX: MAY BE THIS PART IS PROBLEM
' =====================================
' This function is the same as ProcessFolder, but contains relative code to save a relative path at a subfolder level.
Sub ProcessSubFolder(olkSubFld As Outlook.folder)
On Error GoTo GetFolder_Error
If UCase(olkSubFld.Name) Like UCase("*" & strFolderName & "*") = True Then
strHits = olkSubFld.FolderPath
' Save the parent parent path (Which will likely be the folder 'clients'.
SavedPath = olkSubFld.Parent.Parent.FolderPath
Else
Dim olkSubSub As Outlook.folder
For Each olkSubSub In olkSubFld.Folders
ProcessSubSubFolder olkSubSub
Next
Set olkSub = Nothing
End If
GetFolder_Error:
'
End Sub
' Same again as the above.
Sub ProcessSubSubFolder(olkSubSubFld As Outlook.folder)
On Error GoTo GetFolder_Error
If UCase(olkSubSubFld.Name) Like UCase("*" & strFolderName & "*") = True Then
strHits = olkSubSubFld.FolderPath
' Save the parent parent parent folder, which again; will likely be the 'clients' folder.
SavedPath = olkSubSubFld.Parent.Parent.Parent.FolderPath
End If
Set olkSubSub = Nothing
GetFolder_Error:
'
Exit Sub
End Sub
' This function is used to return a vb outlook folder object of a string value relative path descriptor.
' Basically turns '\\example@example.com\Inbox\TestFolder\TestFolder' string value as an Outlook.folder object
Function GetFolder(ByVal FolderPath As String) As Outlook.folder
' Prepare our function variables
Dim TestFolder As Outlook.folder
Dim FoldersArray As Variant
Dim i As Integer
' Error handling
On Error GoTo GetFolder_Error
' Parse our string and remove the root definition.
If Left(FolderPath, 2) = "\\" Then
FolderPath = Right(FolderPath, Len(FolderPath) - 2)
End If
'Convert folderpath to array
FoldersArray = Split(FolderPath, "\")
Set TestFolder = Application.Session.Folders.item(FoldersArray(0))
' Navigate the array to return the actual folder.
If Not TestFolder Is Nothing Then
For i = 1 To UBound(FoldersArray, 1)
Dim SubFolders As Outlook.Folders
Set SubFolders = TestFolder.Folders
Set TestFolder = SubFolders.item(FoldersArray(i))
If TestFolder Is Nothing Then
Set GetFolder = Nothing
End If
Next
End If
'Return the TestFolder
Set GetFolder = TestFolder
Exit Function
GetFolder_Error:
Set GetFolder = Nothing
Exit Function
End Function
' N/A
Sub TestGetFolder()
Dim folder As Outlook.folder
Set folder = GetFolder("\\Mailbox - Dan Wilson\Inbox\Customers")
If Not (folder Is Nothing) Then
folder.Display
End If
End Sub
' Начало фрагмента A
Private Sub oInspectors_NewInspector(ByVal Inspector As Inspector)
If Inspector.CurrentItem.Class = olMail Then
If Len(Inspector.CurrentItem.EntryID) = 0 Then
Set oMsg = Inspector.CurrentItem
End If
End If
End Sub
' Конец фрагмента A
Private Sub oMsg_Send(Cancel As Boolean)
Dim oRecipient As Recipient, oBusinessFolder As MAPIFolder, oEmailCopy As MailItem
For Each oRecipient In oMsg.Recipients
' Начало фрагмента B
If InStr(1, oRecipient.Address, "gmail.com") Then
' Конец фрагмента B
oMsg.DeleteAfterSubmit = True
Set oBusinessFolder = Application.Session.GetDefaultFolder(olFolderInbox).Parent.Folders(BUSINESS_FOLDER)
Set oEmailCopy = oMsg.Copy
oEmailCopy.Move oBusinessFolder
Exit For
End If
Next
End Sub
Private Sub oMsg_Read(Cancel As Boolean)
Dim oRecipient As Recipient, oBusinessFolder As MAPIFolder, oEmailCopy As MailItem
For Each oRecipient In oMsg.Recipients
' Начало фрагмента B
If InStr(1, oRecipient.Address, "gmail.com") Then
' Конец фрагмента B
oMsg.DeleteAfterSubmit = True
Set oBusinessFolder = Application.Session.GetDefaultFolder(olFolderInbox).Parent.Folders(BUSINESS_FOLDER)
Set oEmailCopy = oMsg.Copy
oEmailCopy.Move oBusinessFolder
Exit For
End If
Next
End Sub