下記のコードをVBAエディターに張り付けてください。
※赤字の部分を使用者の名前に変更してください。
以下のルールでメールを書き出します。
- 会議招待メール → 自動で承諾し、削除
- CC に使用者の名前が含まれ、本文の最初の数行にないメール
- 宛先にユーザーの名前がないメール
上記以外のメールは重要度が高いので書き出さない
宛先がユーザーだけの場合は、広告メールの可能性があるので、確認して不要なアドレスは保存しておき削除リストにある場合はメールを削除
Option Explicit
' Main procedure for email organization
Sub メール整理Claud()
Dim objNS As NameSpace
Dim srcFolder As MAPIFolder
Dim destFolder As MAPIFolder
Dim plantFolder As MAPIFolder
Dim saveDataFilename As String
Dim eraseAddressList() As String
Dim npointer As Long
Dim eraseAddressFile As String
Dim nameFilter As String
Dim jsonData As String
On Error GoTo ErrorHandler
' Configuration settings
Const DEBUG_MODE As Boolean = False
nameFilter = "Your Name"
eraseAddressFile = "C:\Users\Public\Taro\Outlook File\er_address.txt"
' Validate that address file exists
If Dir(eraseAddressFile) = "" Then
MsgBox "アドレスファイルが見つかりません: " & eraseAddressFile, vbExclamation
Exit Sub
End If
' Initialize Outlook folders
Set objNS = Application.GetNamespace("MAPI")
Set srcFolder = objNS.GetDefaultFolder(olFolderInbox)
' Get destination folder from user
Set destFolder = objNS.PickFolder
If destFolder Is Nothing Then Exit Sub
If destFolder.EntryID = srcFolder.EntryID Then
MsgBox "送信元と同じフォルダが選択されました。", vbExclamation
Exit Sub
End If
' Get plant management folder
On Error Resume Next
Set plantFolder = srcFolder.Folders("プラント管理メール")
On Error GoTo ErrorHandler
If plantFolder Is Nothing Then
MsgBox "プラント管理メール フォルダが見つかりません。フォルダを作成してください。", vbExclamation
Exit Sub
End If
' Get filename for JSON export
saveDataFilename = GetSaveFilename()
If saveDataFilename = "" Then
MsgBox "終了します。", vbInformation
GoTo Cleanup
End If
' Load the address list for automatic deletion
npointer = LoadAddressList(eraseAddressList, eraseAddressFile)
If npointer < 0 Then GoTo Cleanup
' Process meeting requests
ProcessMeetingRequests srcFolder
' Sort and process mail items
Dim sortedItems() As mailItem
Dim itemCount As Long
itemCount = GetSortedMailItems(srcFolder, sortedItems)
' Process mail items and generate JSON
jsonData = ProcessMailItems(sortedItems, itemCount, nameFilter, destFolder, plantFolder, _
eraseAddressList, npointer, eraseAddressFile, DEBUG_MODE)
' Save JSON data to file
SaveDataAsUTF8 jsonData, saveDataFilename
MsgBox "終了しました。", vbOKOnly, "終了"
Cleanup:
Set objNS = Nothing
Set srcFolder = Nothing
Set destFolder = Nothing
Set plantFolder = Nothing
Exit Sub
ErrorHandler:
MsgBox "エラーが発生しました: " & Err.Description, vbCritical
Resume Cleanup
End Sub
' Process all mail items and generate JSON data
Function ProcessMailItems(items() As mailItem, itemCount As Long, nameFilter As String, _
destFolder As MAPIFolder, plantFolder As MAPIFolder, _
ByRef eraseAddressList() As String, ByRef npointer As Long, _
eraseAddressFile As String, isDebug As Boolean) As String
Dim mailItem As mailItem
Dim recipientType As Integer
Dim senderAddress As String
Dim jsonArray As String
Dim isFirstItem As Boolean
Dim i As Long
Dim result As Integer
jsonArray = "["
isFirstItem = True
For i = 0 To itemCount - 1
Set mailItem = items(i)
recipientType = CheckRecipientType(mailItem, nameFilter)
senderAddress = GetSenderAddress(mailItem)
Select Case recipientType
Case 7, 8 ' Plant management emails
If Not isDebug Then mailItem.Move plantFolder
Case 0 ' No recipients match filter
If Not isDebug Then mailItem.Move destFolder
Case 2 ' CC recipient and not in first 3 lines
If Not CheckNameInFirstLines(mailItem, nameFilter) Then
If Not isFirstItem Then jsonArray = jsonArray & ","
jsonArray = jsonArray & CreateMailItemJSON(mailItem)
isFirstItem = False
If Not isDebug Then mailItem.Move destFolder
End If
Case 9 ' Only recipient and has sender address
If senderAddress <> "" Then
result = HandleSenderAddress(mailItem, eraseAddressList, npointer, eraseAddressFile)
If Not isDebug And result = 1 Then mailItem.Delete
End If
End Select
Next i
jsonArray = jsonArray & "]"
ProcessMailItems = jsonArray
End Function
' Gets mail items from folder and sorts by received time (newest first)
Function GetSortedMailItems(folder As MAPIFolder, ByRef items() As mailItem) As Long
Dim allItems As items
Dim item As Object
Dim mailItem As mailItem
Dim i As Long
Dim count As Long
' First count the actual mail items
count = 0
For Each item In folder.items
If TypeOf item Is mailItem Then count = count + 1
Next
If count = 0 Then
GetSortedMailItems = 0
Exit Function
End If
' Dimension the array to exact size needed
ReDim items(0 To count - 1) As mailItem
' Populate the array with mail items
i = 0
For Each item In folder.items
If TypeOf item Is mailItem Then
Set items(i) = item
i = i + 1
End If
Next
' Use QuickSort on the array
QuickSortMailItems items, 0, count - 1
GetSortedMailItems = count
End Function
' Optimized QuickSort algorithm for mail items (newest first)
Sub QuickSortMailItems(ByRef items() As mailItem, ByVal low As Long, ByVal high As Long)
Dim pivot As Date
Dim i As Long, j As Long
Dim tempItem As mailItem
If low < high Then
' Use middle item as pivot to improve performance on already sorted data
pivot = items((low + high) \ 2).ReceivedTime
i = low
j = high
Do
' Find item on left that should be on right
While items(i).ReceivedTime > pivot And i < high
i = i + 1
Wend
' Find item on right that should be on left
While pivot > items(j).ReceivedTime And j > low
j = j - 1
Wend
' Swap the items
If i <= j Then
Set tempItem = items(i)
Set items(i) = items(j)
Set items(j) = tempItem
i = i + 1
j = j - 1
End If
Loop Until i > j
' Recursively sort the sub-arrays
If low < j Then QuickSortMailItems items, low, j
If i < high Then QuickSortMailItems items, i, high
End If
End Sub
' Check recipient type and return appropriate code
Function CheckRecipientType(mailItem As mailItem, nameFilter As String) As Integer
Dim recipient As recipient
Dim subject As String
Dim sender As String
subject = mailItem.subject
sender = mailItem.senderName
' Check for plant management system emails
If Left(subject, 10) = "プラント管理システム" Then
CheckRecipientType = 8
Exit Function
End If
If sender = "crepf-sys@nacoo.net" And Left(subject, 5) = "エラー発生" Then
CheckRecipientType = 8
Exit Function
End If
If Left(sender, 2) = "CC" And InStr(1, subject, "プラントデータ") <> 0 Then
CheckRecipientType = 7
Exit Function
End If
' Check recipients
For Each recipient In mailItem.recipients
If InStr(recipient.Name, nameFilter) <> 0 Then
If mailItem.recipients.count = 1 Then
CheckRecipientType = 9 ' Only recipient
Else
CheckRecipientType = recipient.Type ' Type: BCC=3, CC=2, TO=1, Originator=0
End If
Exit Function
End If
Next
CheckRecipientType = 0 ' No matching recipients
End Function
' Get sender's email address
Function GetSenderAddress(mailItem As mailItem) As String
If mailItem.SenderEmailType = "EX" Then
GetSenderAddress = ""
Else
GetSenderAddress = mailItem.SenderEmailAddress
End If
End Function
' Check if name appears in first few lines of email body
Function CheckNameInFirstLines(mailItem As mailItem, nameFilter As String) As Boolean
Dim topLines As String
' Get top lines of body (6 rows to account for HTML formatting)
topLines = GetTopLines(mailItem.body, 6, mailItem.BodyFormat)
CheckNameInFirstLines = (InStr(topLines, nameFilter) <> 0)
End Function
' Get the top N lines of text
Function GetTopLines(text As String, lineCount As Integer, format As OlBodyFormat) As String
Dim lineBreak As String
Dim position As Long
Dim nextPosition As Long
Dim i As Integer
Dim result As String
' Determine line break character based on format
If format = olFormatHTML Then
lineBreak = vbCrLf
Else
lineBreak = vbLf
End If
position = 1
result = ""
For i = 1 To lineCount
nextPosition = InStr(position, text, lineBreak, vbBinaryCompare)
If nextPosition = 0 Then
' No more line breaks, include rest of text
result = result & Mid(text, position)
Exit For
Else
' Add current line to result
result = result & Mid(text, position, nextPosition - position + Len(lineBreak))
position = nextPosition + Len(lineBreak)
End If
Next i
GetTopLines = result
End Function
' Process meeting requests automatically
Sub ProcessMeetingRequests(folder As MAPIFolder)
Dim item As Object
Dim meetingItem As meetingItem
Dim appointment As AppointmentItem
On Error Resume Next
For Each item In folder.items
If TypeOf item Is meetingItem Then
Set meetingItem = item
Set appointment = meetingItem.GetAssociatedAppointment(True)
If Not appointment Is Nothing Then
appointment.Respond olResponseAccepted, True
meetingItem.Delete
End If
End If
Next
On Error GoTo 0
End Sub
' Handle sender address processing
Function HandleSenderAddress(mailItem As mailItem, ByRef eraseAddressList() As String, _
ByRef npointer As Long, eraseAddressFile As String) As Integer
Dim result As Integer
Dim senderAddress As String
Dim addressStatus As Integer
senderAddress = mailItem.SenderEmailAddress
addressStatus = CheckAddressInList(senderAddress, eraseAddressList)
Select Case addressStatus
Case 0 ' Delete
HandleSenderAddress = 1
Case 9 ' Not in list, ask user
result = InquireAboutAddress(mailItem)
' Ensure array has enough space
If UBound(eraseAddressList, 2) < npointer Then
ReDim Preserve eraseAddressList(0 To 1, 0 To npointer + 10)
End If
If result = vbYes Then ' Delete
eraseAddressList(0, npointer) = senderAddress
eraseAddressList(1, npointer) = 0
npointer = npointer + 1
SaveAddressToFile senderAddress, 0, eraseAddressFile
HandleSenderAddress = 1
ElseIf result = vbNo Then ' Keep
eraseAddressList(0, npointer) = senderAddress
eraseAddressList(1, npointer) = 1
npointer = npointer + 1
SaveAddressToFile senderAddress, 1, eraseAddressFile
HandleSenderAddress = 0
End If
Case Else ' Keep
HandleSenderAddress = 0
End Select
End Function
' Check if address exists in deletion list
Function CheckAddressInList(address As String, ByRef addressList() As String) As Integer
Dim i As Long
If Not IsArrayInitialized(addressList) Then
CheckAddressInList = 9 ' Not in list
Exit Function
End If
For i = 0 To UBound(addressList, 2)
If addressList(0, i) = address Then
CheckAddressInList = addressList(1, i) ' Return status (0=delete, 1=keep)
Exit Function
End If
Next
CheckAddressInList = 9 ' Not in list
End Function
' Load address list from file
Function LoadAddressList(ByRef addressList() As String, filename As String) As Long
Dim fileNumber As Integer
Dim address As String
Dim flag As String
Dim i As Long
On Error GoTo ErrorHandler
' Initialize array
ReDim addressList(0 To 1, 0 To 10)
' Check if file exists
If Dir(filename) = "" Then
LoadAddressList = 0
Exit Function
End If
' Open file
fileNumber = FreeFile
Open filename For Input As #fileNumber
i = 0
Do Until EOF(fileNumber)
' Read address and flag
Input #fileNumber, address, flag
' Resize array if needed
If i > UBound(addressList, 2) Then
ReDim Preserve addressList(0 To 1, 0 To i + 10)
End If
' Store values
addressList(0, i) = address
addressList(1, i) = Val(flag)
i = i + 1
Loop
Close #fileNumber
LoadAddressList = i
Exit Function
ErrorHandler:
MsgBox "アドレスリストの読み込み中にエラーが発生しました: " & Err.Description, vbCritical
If fileNumber > 0 Then Close #fileNumber
LoadAddressList = -1
End Function
' Save address and flag to file
Sub SaveAddressToFile(address As String, flag As Integer, filename As String)
Dim fileNumber As Integer
On Error Resume Next
fileNumber = FreeFile
Open filename For Append As #fileNumber
Write #fileNumber, address, flag
Close #fileNumber
End Sub
' Show dialog to ask about address
Function InquireAboutAddress(mailItem As mailItem) As Integer
Dim senderName As String
Dim senderAddress As String
Dim subject As String
senderName = mailItem.senderName
senderAddress = mailItem.SenderEmailAddress
subject = mailItem.subject
Load InqDlg
InqDlg.StartUpPosition = 1
InqDlg.Caption = "削除リストに追加しますか?"
InqDlg.Label_sender.Caption = senderName
InqDlg.Label_adress = senderAddress
InqDlg.Label_subject = subject
InqDlg.Show
InquireAboutAddress = InqDlg.DialogResult
End Function
' Create JSON representation of mail item
Function CreateMailItemJSON(mailItem As mailItem) As String
Dim json As String
Dim toRecipients As String
Dim ccRecipients As String
Dim bccRecipients As String
Dim attachments As String
Dim recipient As Outlook.recipient
Dim attachment As Outlook.attachment
Dim bodyText As String
' Process To recipients
toRecipients = "["
For Each recipient In mailItem.recipients
If recipient.Type = olTo Then
If toRecipients <> "[" Then toRecipients = toRecipients & "," & vbCrLf & vbTab & vbTab
toRecipients = toRecipients & """" & recipient.Name & """"
End If
Next recipient
If Len(toRecipients) > 1 Then toRecipients = toRecipients & vbCrLf & vbTab
toRecipients = toRecipients & "]"
' Process CC recipients
ccRecipients = "["
For Each recipient In mailItem.recipients
If recipient.Type = olCC Then
If ccRecipients <> "[" Then ccRecipients = ccRecipients & "," & vbCrLf & vbTab & vbTab
ccRecipients = ccRecipients & """" & recipient.Name & """"
End If
Next recipient
If Len(ccRecipients) > 1 Then ccRecipients = ccRecipients & vbCrLf & vbTab
ccRecipients = ccRecipients & "]"
' Process BCC recipients
bccRecipients = "["
For Each recipient In mailItem.recipients
If recipient.Type = olBCC Then
If bccRecipients <> "[" Then bccRecipients = bccRecipients & "," & vbCrLf & vbTab & vbTab
bccRecipients = bccRecipients & """" & recipient.Name & """"
End If
Next recipient
If Len(bccRecipients) > 1 Then bccRecipients = bccRecipients & vbCrLf & vbTab
bccRecipients = bccRecipients & "]"
' Process attachments
attachments = "["
For Each attachment In mailItem.attachments
If attachments <> "[" Then attachments = attachments & "," & vbCrLf & vbTab & vbTab
attachments = attachments & """" & EscapeJSON(attachment.filename) & """"
Next attachment
If Len(attachments) > 1 Then attachments = attachments & vbCrLf & vbTab
attachments = attachments & "]"
' Process body (truncate if too long)
bodyText = TruncateLongEmail(mailItem.body)
' Build JSON structure
json = "{" & vbCrLf
json = json & vbTab & """ReceivedTime"": """ & format(mailItem.ReceivedTime, "yyyy-mm-dd hh:nn:ss") & """," & vbCrLf
json = json & vbTab & """SenderName"": """ & EscapeJSON(mailItem.senderName) & """," & vbCrLf
json = json & vbTab & """Subject"": """ & EscapeJSON(mailItem.subject) & """," & vbCrLf
json = json & vbTab & """To"": " & toRecipients & "," & vbCrLf
json = json & vbTab & """CC"": " & ccRecipients & "," & vbCrLf
json = json & vbTab & """BCC"": " & bccRecipients & "," & vbCrLf
json = json & vbTab & """Attachments"": " & attachments & "," & vbCrLf
json = json & vbTab & """Body"": """ & EscapeJSON(bodyText) & """" & vbCrLf
json = json & "}"
CreateMailItemJSON = json
End Function
' Truncate long emails to a reasonable size
Function TruncateLongEmail(emailBody As String) As String
Const MAX_LENGTH As Long = 10000
Dim result As String
Dim position As Long
Dim nextMatchPos As Long
' If email is already within limit, return as is
If Len(emailBody) <= MAX_LENGTH Then
TruncateLongEmail = emailBody
Exit Function
End If
' Start building truncated content
result = ""
position = 1
Do While position > 0
' Find next matching line position
nextMatchPos = FindFirstMatchingLine(emailBody, position)
' If no more matching lines are found, append the remaining text
If nextMatchPos = 0 Then
If Len(result & Mid(emailBody, position)) > MAX_LENGTH Then
Exit Do
End If
result = result & Mid(emailBody, position)
Exit Do
End If
' Append text up to the matching position
If Len(result & Mid(emailBody, position, nextMatchPos - position)) > MAX_LENGTH Then
Exit Do
End If
result = result & Mid(emailBody, position, nextMatchPos - position)
' Update position to continue after the match
position = InStr(nextMatchPos, emailBody, vbCrLf)
If position = 0 Then
Exit Do
Else
position = position + 2
End If
Loop
TruncateLongEmail = result
End Function
' Find email format patterns like reply headers
Function FindFirstMatchingLine(text As String, Optional startPos As Long = 1) As Long
Dim regEx As Object
Dim matches As Object
Dim searchText As String
' Adjust starting position
If startPos < 1 Then startPos = 1
If startPos > Len(text) Then
FindFirstMatchingLine = 0
Exit Function
End If
' Create regex object
Set regEx = CreateObject("VBScript.RegExp")
regEx.Pattern = "(\d{4}年\d{1,2}月\d{1,2}日\(.\) \d{1,2}:\d{2} .+ <.+@.+\..+>:" & _
"|差出人: .+ <.+@.+\..+>" & _
"|-+ Original Message -+\nFrom : \"".+\""<.+@.+\..+>)"
regEx.IgnoreCase = True
regEx.Global = False
' Get substring from starting position
searchText = Mid(text, startPos)
' Execute regex
Set matches = regEx.Execute(searchText)
' Return match position if found
If matches.count > 0 Then
FindFirstMatchingLine = startPos + matches(0).FirstIndex - 1
Else
FindFirstMatchingLine = 0
End If
End Function
' Escape special characters for JSON output
Function EscapeJSON(text As String) As String
Dim result As String
result = text
result = Replace(result, "\", "\\")
result = Replace(result, """", "\""")
result = Replace(result, vbCrLf, "\n")
result = Replace(result, vbLf, "\n")
result = Replace(result, vbCr, "\n")
result = Replace(result, vbTab, " ")
' Remove control characters
result = RemoveControlCharacters(result)
EscapeJSON = result
End Function
' Remove control characters from text
Function RemoveControlCharacters(text As String) As String
Dim i As Long
Dim charCode As Integer
Dim result As String
result = ""
For i = 1 To Len(text)
charCode = Asc(Mid(text, i, 1))
' Skip control characters (ASCII 0-31, 127)
If charCode >= 32 And charCode <> 127 Then
result = result & Mid(text, i, 1)
End If
Next i
RemoveControlCharacters = result
End Function
' Get save filename with date-based naming
Function GetSaveFilename() As String
Dim xlApp As Object
Dim fileDialog As Object
Dim selectedFolder As String
' Create Excel application to use FileDialog
Set xlApp = CreateObject("Excel.Application")
Set fileDialog = xlApp.fileDialog(msoFileDialogFolderPicker)
With fileDialog
.Title = "メールデータの保存先フォルダを選択してください"
If .Show = -1 Then
selectedFolder = .SelectedItems(1)
Else
GetSaveFilename = ""
Set fileDialog = Nothing
xlApp.Quit
Set xlApp = Nothing
Exit Function
End If
End With
' Create date-based filename
GetSaveFilename = CreateDatedFilename(selectedFolder, "maildata", "json")
' Clean up
Set fileDialog = Nothing
xlApp.Quit
Set xlApp = Nothing
End Function
' Create dated filename with increment for existing files
Function CreateDatedFilename(folderPath As String, prefix As String, extension As String) As String
Dim filePath As String
Dim i As Long
Dim today As Date
today = Date
i = 0
Do
' Format: prefix + YYMMDD + sequential number + extension
filePath = folderPath & "\" & prefix & format(today, "yymmdd") & format(i, "000") & "." & extension
' Check if file exists
If Dir(filePath) = "" Then
Exit Do
End If
i = i + 1
Loop
CreateDatedFilename = filePath
End Function
' Save data to file with UTF-8 encoding (no BOM)
Sub SaveDataAsUTF8(data As String, filename As String)
Dim stream As Object
On Error GoTo ErrorHandler
' Create ADODB Stream object
Set stream = CreateObject("ADODB.Stream")
With stream
.Charset = "UTF-8"
.Type = 2 ' Text mode
.Open
.WriteText data
' Remove BOM
.position = 0
.Type = 1 ' Binary mode
.position = 3 ' Skip BOM bytes
Dim byteData() As Byte
byteData = .Read
.Close
' Write data without BOM
.Open
.Write byteData
.SaveToFile filename, 2 ' ForOverwrite
.Close
End With
Set stream = Nothing
Exit Sub
ErrorHandler:
MsgBox "ファイル保存中にエラーが発生しました: " & Err.Description, vbCritical
If Not stream Is Nothing Then
On Error Resume Next
stream.Close
Set stream = Nothing
End If
End Sub
' Check if array is initialized
Function IsArrayInitialized(arr As Variant) As Boolean
On Error Resume Next
IsArrayInitialized = IsArray(arr) And Not IsError(LBound(arr, 1))
On Error GoTo 0
End Function