rudi

[solved] Extract "SENT" timestamp from Outlook MSG file

21 posts in this topic

#1 ·  Posted (edited)

Hello.

<edit>

see my 2nd but last posting in this thread to find a script doing the following

  • Create a GUI with a "file drag drop enabled" input control.
  • When Outlook Emails are saved to disk a *.MSG file is created. When such MSG file(s) are draged on this input control, the "receive date" is retrieved from the MSG file, with the use of OutlookEX (UDF written by "water").
  • The MSG file's timestamp (last modified) is set to the retrieved "receive date", so that the FS timestamp reflects the point of time, this email was originally received.
  • Dropping multiple MSG files within one drag & drop operation is supported.
  • Files not matching the naming scheme *.MSG are ignored.
  • Folders are ignored.

Limitations:

  • To retrieve the "receive date", OutlookEX has to open the MSG file using OUTLOOK.EXE. That's opening a window. It's immediately minimized, but will "flicker" on your screen for a very short time.
  • I do not check, if this *.MSG file REALLY IS a Outlook saved file (no file format error handling).

 

Thanks to water for OutlookEX and the patient help to get this running. :thumbsup:

</edit>

 

 

First of all, this is what I shall do: A coworker is saving important emails (Outlook 2010, Exchange 2010) to file system folders from time to time.

The resulting MSG files have a timestamp reflecting the point of time, the emails were saved to disk. He asked me to write a script to touch these files in a manner, that the "last modified" timestamp is set to the point of time that email was originally received.

 

 

So now I'd like to extract from these Outlook 2010 *.MSG files the "received" timestamp and desperately fail to understand the MSG files' structure.

[MS-OXMSG] is a description of the file format of MSG files, hm, I don't get it :mad2:

 

I'm aware of the UDFs Outlook and OutlookEX, but didn't get either if they might be helpful to handle MSG saved email files.

 

Maybe there is a command line tool that's processing MSG files in the same style like EML_PROCESS?

 

Any suggestions appreciated. 

 

Regards, Rudi.

Edited by rudi

Earth is flat, pigs can fly, and Nuclear Power is SAFE!

Share this post


Link to post
Share on other sites



Should be possible using the OutlookEX UDF.
In short:
Use function _OL_ItemCreate and pass the msg file as template (parameter 4) for the new item. Extract the needed properties using _OL_ItemGet, then drop the created new item.

 


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

Thanks for your reply.

This is my first try, not working at all, what's the name of the property "Date, this email was received" ??

 

#include "C:\temp\Email-Receive-to-Savedate\udf\OutlookEX.au3"
$MsgFile="c:\temp\Email-Receive-to-Savedate\test.msg"


Global $oItem
Global $oOutlook = _OL_Open()
If @error <> 0 Then Exit MsgBox(16, "OutlookEX UDF", "Error creating a connection to Outlook. @error = " & @error & ", @extended = " & @extended)
Global $Result = _OL_TestEnvironmentCreate($oOutlook)
If @error <> 0 Then Exit MsgBox(16, "OutlookEX UDF - Manage Test Environment", "Error creating the test environment. @error = " & @error & ", @extended = " & @extended)



$oMail=_OL_ItemCreate($oOutlook, $olMailItem,@TempDir,$MsgFile)

$ReceiveDate=_OL_ItemGet($oMail,"timestamp")
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $ReceiveDate = ' & $ReceiveDate & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console

; this is opening an Outlook Reminder "TestAppointment-Conflict (timestamp = now() minus 10 minutes)
; and [OutlookEX UDF - Manage Test Environment] --> "OK Error creating the test environment. @error = 509, @extended = 4"



; delete object $oMail ???

Regards, Rudi.


Earth is flat, pigs can fly, and Nuclear Power is SAFE!

Share this post


Link to post
Share on other sites

This returnes the ReceivedTime property. Unfortunately this is the time when the new mail item is being created.

#include <OutlookEX.au3>

$oOL = _OL_Open()
$oItem = _OL_ItemCreate($oOL, $olMailItem, "", "C:\temp\test.msg")
$aProperties = _OL_ItemGet($oOL, $oItem, Default, "ReceivedTime")
MsgBox(0, "Info", "Mail received: " & $aProperties[1][1] & @CRLF & "Press OK to close the mail")
$oItem.Close(1) ; Close and discard the item
_OL_Close($oOL)

Will do some further investigation.


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

This works for me:

#include <OutlookEX.au3>

$oOL = _OL_Open()
ShellExecuteWait("C:\temp\test.msg")
$oItem = $oOL.ActiveInspector.CurrentItem
$aProperties = _OL_ItemGet($oOL, $oItem, Default, "ReceivedTime")
MsgBox(0, "Info", "Mail received: " & $aProperties[1][1] & @CRLF & "Press OK to close the mail")
$oItem.Close(1) ; Close and discard the item
_OL_Close($oOL)

 


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

Thanks a lot, it's working fine, when I use it for one single file.

When monitoring a "input directory", then the script crashes, the last processed email (mostly the 1st or the 2nd one in the Dir) remains open, and the script below generates this output:

Results:
Valid file found: AW  Bei IBM hinterlegtes SLA für Hardware Ersatzlieferung   NEXT  Business Day!   Ticket  RCMS 01VVVCJ 724 .msg
ShellExecuteWait done (debug info)
@@ Debug(59) : $oItem =  >Error code: 4
@@ Debug(61) : $aProperties =  >Error code: 1

 

Sometimes several MSG files are correctly processed. It looks like OUTLOOK.EXE should *NOT* run already, when using this script?

 

#include <GUIConstantsEx.au3>
#include <OutlookEX.au3>

$MsgDir = "C:\temp\Email-Receive-to-Savedate\"
$DoneDir = "C:\temp\Email-Receive-to-Savedate\done\"
DirCreate($DoneDir)

Run("Explorer.exe /e," & $MsgDir)

$MsgMatch = "*.msg"

$GuiTitle = "Touch Email MSG files to ""receive date"""
$w = 400
$h = 600
$labelTxt = "To touch Emails' file system time stamp, drop them into the folder, that's going to open now. Once processed, you will find them with the appropriate time stamp set in the subfolder ""done""."
$EditResultTxt = "Results:" & @CRLF
$NothingToDo = "Warte auf MSG Files." & @CRLF



GUICreate($GuiTitle, $w, $h)
GUICtrlCreateLabel($labelTxt, 20, 20, $w - 40, 50)
$EditResults = GUICtrlCreateEdit($EditResultTxt, 20, 70, $w - 40, $h - 130)
$exit = GUICtrlCreateButton("Programm beenden", 20, $h - 45, $w - 40, 30)
GUISetState()

AdlibRegister("CheckForExit")

While 1

    $search = FileFindFirstFile($MsgDir & $MsgMatch)
    If $search = -1 Then
        Sleep(10) ; wait for emails to be saved to disk to get touched
        If Not (StringRight($EditResultTxt, StringLen($NothingToDo)) = $NothingToDo) Then LabelUdate($NothingToDo)
    Else
        While 1
            $msg = FileFindNextFile($search)
            $err = @error
            $ext = @extended
            $MsgFile = $MsgDir & $msg

            If $err Then
                ConsoleWrite("Keine weiteren MSG files zu finden" & @CRLF)
                ExitLoop
            EndIf

            If $ext Then
                ContinueLoop ; very funny to drop some .MSG *DIRECTORY* here...
            EndIf

            $oOL = _OL_Open()

            LabelUdate("Valid file found: " & $msg & @CRLF)
            ShellExecuteWait($MsgFile)
            LabelUdate("ShellExecuteWait done (debug info)" & @CRLF)
            $oItem = $oOL.ActiveInspector.CurrentItem
            LabelUdate('@@ Debug(' & @ScriptLineNumber & ') : $oItem = ' & $oItem & ' >Error code: ' & @error & @CRLF)
            $aProperties = _OL_ItemGet($oOL, $oItem, Default, "ReceivedTime")
            LabelUdate('@@ Debug(' & @ScriptLineNumber & ') : $aProperties = ' & $aProperties & ' >Error code: ' & @error & @CRLF) ;### Debug Console
            $ReceiveDate = $aProperties[1][1]
            LabelUdate($ReceiveDate & @CRLF)
            $result = $oItem.Close(1) ; Close and discard the item
            LabelUdate('@@ Debug(' & @ScriptLineNumber & ') : $result = ' & $result & ' >Error code: ' & @error & @CRLF) ;### Debug Console

            LabelUdate("Waiting until the file is moved .")

            $CopyTo = $DoneDir & $msg
            While FileMove($MsgFile, $CopyTo, 1 + 8) = 0
                Sleep(100)
                LabelUdate(".")
            WEnd
            LabelUdate(@CRLF & "Waiting until the file is unlocked to be touched.")
            While FileSetTime($CopyTo, $ReceiveDate) = 0
                Sleep(100)
                LabelUdate("-")
            WEnd
            If FileSetTime($CopyTo, $ReceiveDate) Then
                LabelUdate(@CRLF & "Neuer Zeitstempel: " & TS_Readable($ReceiveDate) & @CRLF)
            Else
                LabelUdate(@CRLF & "Fehler beim Setzen des Zeitstempels!" & @CRLF & TS_Readable($ReceiveDate) & @CRLF)
            EndIf

            _OL_Close($oOL)
        WEnd
    EndIf
    FileClose($search)
WEnd



Func LabelUdate($_txt)
    $EditResultTxt &= $_txt
    GUICtrlSetData($EditResults, $EditResultTxt)
    ClipPut($EditResultTxt)
EndFunc   ;==>LabelUdate




Func CheckForExit()
    Switch GUIGetMsg()
        Case $exit
            MsgBox(0, "Abbruch durch Benutzer", "Programm endet jetzt.")
            Exit
    EndSwitch
EndFunc   ;==>CheckForExit

Func TS_Readable($_String)
    If Not StringLen($_String) = 14 Then
        Return ("No valid Timestamp: " & $_String)
    Else
        Local $foo = StringLeft($_String, 4) ; YYYY
        $foo &= "-" & StringMid($_String, 5, 2) ; MM
        $foo &= "-" & StringMid($_String, 7, 2) ; DD
        $foo &= " " & StringMid($_String, 9, 2) ; hh
        $foo &= ":" & StringMid($_String, 11, 2) ; mm
        $foo &= ":" & StringMid($_String, 13, 2) ; ss
        Return $foo
    EndIf
EndFunc   ;==>TS_Readable

 

A bit confused, as it's working fine with a single file in the same folder...

 

Regards, Rudi.


Earth is flat, pigs can fly, and Nuclear Power is SAFE!

Share this post


Link to post
Share on other sites

Should make no difference when Outlook is already running.

Could you please insert a Sleep(1000) after ShellExecuteWait? Maybe this helps.

 


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

Hello.

Yes, this sleep(1000) seems to do the trick.

So obviously I miss something about ShellExecuteWait, shouldn't this work that way, that the script continues just *AFTER* the launched program was terminated again? I wondered that point before, because the line examining the created object ( that

$oItem = $oOL.ActiveInspector.CurrentItem

is placed within the script below the ShellExecuteWait. So I already wondered, how the object can be examined, when the statement is placed below "programwait --> terminated".

 

Finally another question: Is it possible to suppress the "Email Window" to appear on the screen? Either "open minimized without task bar button", or, if this isn't possible, open the window at screen coordinates that are outside the visible screen?

 

 

Regards, Rudi.


Earth is flat, pigs can fly, and Nuclear Power is SAFE!

Share this post


Link to post
Share on other sites

I assume it works this way:
As we tell Windows to open the msg file with the application associated to this file type it ends as soon as this task has been finished. It doesn't wait until Outlook has been closed because the application hasn't been started by ShellExecuteWait.
If you really want to be sure the mail item has been opened and to not loose too much time by using a fixed sleep interval you could loop until

$oItem = $oOL.ActiveInspector.CurrentItem

does not return an error.

 

Question 2: I think you could set the ActivInspector to minimized.

$oL.ActiveInspector.WindowState = 1 ; Set the Window to minimized.

 


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

Again, thanks for your reply.

 

  • When I drag-drop emails to the monitored File System Folder, I 'ALWAYS* have to close Outlook, then the script is working fine. Starting OUTLOOK.EXE again is locking the "next MSG to be processed".
  • When I drag-drop *EXISTING* MSG files from some other location to the monitored folder, it doesn't seem to matter, if OUTLOOK.EXE is already running.

 

Currently this is my code now, it's faster, but still just processing one MSG file in about 4 seconds:

#include <GUIConstantsEx.au3>
#include <OutlookEX.au3>

$MsgDir = "C:\temp\Email-Receive-to-Savedate\"
$DoneDir = "C:\temp\Email-Receive-to-Savedate\done\"
DirCreate($DoneDir)

Run("Explorer.exe /e," & $MsgDir)

$MsgMatch = "*.msg"

$GuiTitle = "Touch Email MSG files to ""receive date"""
$w = Floor(@DesktopWidth /2)
$h = @DesktopHeight - 60
$labelTxt = "To touch Emails' file system time stamp, drop them into the folder, that's going to open now. Once processed, you will find them with the appropriate time stamp set in the subfolder ""done""."
$EditResultTxt = "Results:" & @CRLF
$NothingToDo = @CRLF & @CRLF & "Waiting for MSG Files." & @CRLF



$MyGui=GUICreate($GuiTitle, $w, $h)
GUICtrlCreateLabel($labelTxt, 20, 20, $w - 40, 50)
$EditResults = GUICtrlCreateEdit($EditResultTxt, 20, 70, $w - 40, $h - 130)
$exit = GUICtrlCreateButton("Programm beenden", 20, $h - 45, $w - 40, 30)
GUISetState()
AdlibRegister("CheckForExit")

While 1

    $search = FileFindFirstFile($MsgDir & $MsgMatch)
    If $search = -1 Then
        Sleep(200) ; wait for emails to be saved to disk to get touched
        If Not (StringRight($EditResultTxt, StringLen($NothingToDo)) = $NothingToDo) Then LabelUdate($NothingToDo)
        WinSetOnTop($GuiTitle,"",0)
    Else
        WinSetOnTop($GuiTitle,$labelTxt,1)
        $EditResultTxt="new MSG files detected, processing ..." & @CRLF
        While 1
            $msg = FileFindNextFile($search)
            $err = @error
            $ext = @extended
            $MsgFile = $MsgDir & $msg

            If $err Then
                ConsoleWrite("Keine weiteren MSG files zu finden" & @CRLF)
                ExitLoop
            EndIf

            If $ext Then
                ContinueLoop ; very funny to drop some .MSG *DIRECTORY* here...
            EndIf

            $oOL = _OL_Open()

            LabelUdate(@CRLF & @CRLF & "Valid file found: " & $msg & @CRLF)
            ShellExecuteWait($MsgFile)
            do
                Sleep(100)
                $oItem = $oOL.ActiveInspector.CurrentItem
            until @error = 0
            $aProperties = _OL_ItemGet($oOL, $oItem, Default, "ReceivedTime")
            $ReceiveDate = $aProperties[1][1]
            LabelUdate("Receive Date: " & TS_Readable($ReceiveDate) & @CRLF)
            $result = $oItem.Close(1) ; Close and discard the item
            LabelUdate("Waiting until the file is moved .")

            $CopyTo = $DoneDir & $msg
            While FileMove($MsgFile, $CopyTo, 1 + 8) = 0
                Sleep(1000)
                LabelUdate(".")
            WEnd
            LabelUdate(@CRLF & "Waiting until the file is unlocked to be touched.")
            While FileSetTime($CopyTo, $ReceiveDate) = 0
                Sleep(1000)
                LabelUdate("-")
            WEnd
            LabelUdate(" done. (OK)")

            _OL_Close($oOL)
        WEnd
    EndIf
    FileClose($search)
WEnd



Func LabelUdate($_txt)
    $EditResultTxt &= $_txt
    GUICtrlSetData($EditResults, $EditResultTxt)
    ClipPut($EditResultTxt)
EndFunc   ;==>LabelUdate




Func CheckForExit()
    Switch GUIGetMsg()
        Case $exit
            GUIDelete($MyGui)
            MsgBox(0, "Abbruch durch Benutzer", "Programm endet jetzt.",3)
            Exit
    EndSwitch
EndFunc   ;==>CheckForExit

Func TS_Readable($_String)
    If Not StringLen($_String) = 14 Then
        Return ("No valid Timestamp: " & $_String)
    Else
        Local $foo = StringLeft($_String, 4) ; YYYY
        $foo &= "-" & StringMid($_String, 5, 2) ; MM
        $foo &= "-" & StringMid($_String, 7, 2) ; DD
        $foo &= " " & StringMid($_String, 9, 2) ; hh
        $foo &= ":" & StringMid($_String, 11, 2) ; mm
        $foo &= ":" & StringMid($_String, 13, 2) ; ss
        Return $foo
    EndIf
EndFunc   ;==>TS_Readable

 

Regards, Rudi.

Edited by rudi
Almost full rewrite

Earth is flat, pigs can fly, and Nuclear Power is SAFE!

Share this post


Link to post
Share on other sites

#11 ·  Posted (edited)

Separate question:

this seems to be the wrong position to minimize the ActiveInspector Window:

ShellExecuteWait($MsgFile)
    do
        Sleep(100)
        $oItem = $oOL.ActiveInspector.CurrentItem
    until @error = 0
    $oL.ActiveInspector.WindowState = 1 ; Set the Window to minimized.
>Running AU3Check (3.3.12.0)  from:C:\Program Files (x86)\AutoIt3  input:C:\temp\Email-Receive-to-Savedate-v2.au3
"C:\temp\Email-Receive-to-Savedate-v2.au3"(62,70) : warning: $oL possibly not declared/created yet
            $oL.ActiveInspector.WindowState = 1 ; Set the Window to minimized.
            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^

The ActiveInspector's Window is open for less than a second. Anyway, it would be nice to supress it.

 

Regards, Rudi.

Edited by rudi

Earth is flat, pigs can fly, and Nuclear Power is SAFE!

Share this post


Link to post
Share on other sites

That's a typo. Should be

$oOL.ActiveInspector.WindowState = 1 ; Set the Window to minimized.

 


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

Hello.

Thanks for your reply.

 

ShellExecuteWait($MsgFile)
            do
                Sleep(100)
                $oItem = $oOL.ActiveInspector.CurrentItem
            until @error = 0
            $oOL.ActiveInspector.WindowState = 1 ; Set the Window to minimized.

 

Can you see, why OUTLOOK.EXE has to be *NOT* running? I'm using Win7-x64 with Outlook 2010.

As soon as I start outlook, the filemove fails, and is proccessed immediatly after terminating outlook.exe

 

Regards, Rudi.


Earth is flat, pigs can fly, and Nuclear Power is SAFE!

Share this post


Link to post
Share on other sites

Do you use #RequireAdmin in your script?


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

Q: #RequireAdmin ?

A: No, I don't, and I also cannot do so: This script is to be used by regular users without local Admin rights.

Also this modified approach (drag-drop the MSG files to some input box) doesn't work as long as OUTLOOK.EXE is running. Well, I think I can live with this approach

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Outfile=z:\Email-Receive-to-SaveDate.exe
#AutoIt3Wrapper_Res_Description=Zeitstempel von Outlook MSG Files im Dateisystem auf "receive date" setzen.
#AutoIt3Wrapper_Res_Fileversion=2.0.0.3
#AutoIt3Wrapper_Res_Fileversion_AutoIncrement=y
#AutoIt3Wrapper_Res_LegalCopyright=(c) 2015 by Rudolf Thilo, IT-Beratung Rudolf Thilo
#AutoIt3Wrapper_Res_SaveSource=y
#AutoIt3Wrapper_Res_Language=1031
#AutoIt3Wrapper_Run_Au3Stripper=y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <GUIConstantsEx.au3>
#include <OutlookEX.au3>
#include <WindowsConstants.au3>


If Not @Compiled Then 
    Opt("trayicondebug", 1)
    Opt("trayautopause", 0)
Else
    Opt("TrayIconHide",1)
EndIf



$MsgMatch = "*.msg"

$GuiTitle = "Email MSG Dateien: Zeitstempel korrigieren"
$labelTxt = "Um das Datei-Datum von Outlook Email Dateien auf dem Server auf das Empfangsdatum zu korrigieren, diese in das weiße Feld in diesem Fenster ziehen."
$NothingToDo = @CRLF & @CRLF & "Waiting for MSG Files." & @CRLF

$resultTxt = ""
$DragDropInfo = "Gespeicherte Email Datei(en) hier hinein ziehen"


$w = 800
$h = 500
$MyGui = GUICreate($GuiTitle, $w, $h, -1, -1, -1, $WS_EX_ACCEPTFILES)
GUICtrlCreateLabel($labelTxt, 20, 20, $w - 40, 50)
$InputFile = GUICtrlCreateInput($DragDropInfo, 20, 70, $w - 40, 40)
GUICtrlSetState(-1, $GUI_DROPACCEPTED)
GUICtrlCreateGroup("Ergebnisse", 20, 120, $w - 40, $h - 180)
$LabelResult = GUICtrlCreateLabel($resultTxt, 30, 135, $w - 55, $h - 205)
$exit = GUICtrlCreateButton("Programm beenden", $w / 2 - 60, $h - 45, 120, 30)
GUISetState()


$RegExMsg = "(?i)(^.*?\.msg$)"

$LastContent = ""

While 1
    Switch GUIGetMsg()
        Case $exit, $GUI_EVENT_CLOSE
            GUIDelete($MyGui)
            MsgBox(0, "Abbruch durch Benutzer", "Bis nächstes Mal!", 3)
            Exit
    EndSwitch

    $input = GUICtrlRead($InputFile)
    If $input <> $DragDropInfo Then
        WinSetOnTop($GuiTitle, "", 1)
        GUICtrlSetState($InputFile, $GUI_DISABLE)
        $MsgFile = StringReplace($input, $DragDropInfo, "")
        If StringInStr($MsgFile, "|") Then ; da wurden mehrere Dateien reingezogen --> Array bilden
            $aMsgFile = StringSplit($MsgFile, "|", 2) ; no counter value in first element of array
            For $foo In $aMsgFile
                FixTimeStamp($foo)
            Next
        Else
            FixTimeStamp($MsgFile)
        EndIf
        WinSetOnTop($GuiTitle, "", 0)
        GUICtrlSetState($InputFile, $GUI_ENABLE)
        LabelUdate(@CRLF & "Warte auf weitere Dateien (drag-drop im Feld oben) ..." & @CRLF)
    EndIf
WEnd

Func FixTimeStamp($_FilePath)
    $resultTxt = StringTrimLeft($resultTxt, StringInStr($resultTxt, @CRLF, 0, -10))
    LabelUdate(@CRLF & "Neues Objekt: " & $_FilePath & @CRLF)
    If StringRegExp($_FilePath, $RegExMsg) Then ; das ist eine MSG Datei
        GUICtrlSetData($InputFile, $DragDropInfo)
        If FileExists($_FilePath) Then
            If StringInStr(FileGetAttrib($_FilePath), "d") Then ; das ist ein Verzeichnis
                LabelUdate("Das ist ein Verzeichnis, keine MSG Datei!" & @CRLF)
                WinSetOnTop($GuiTitle, "", 0)
                MsgBox(48, "Fehler", "Das ist ein Verzeichnis, keine MSG Datei!" & @CRLF & $_FilePath)
                WinSetOnTop($GuiTitle, "", 1)

            Else
                LabelUdate("MSG Datei erkannt." & @CRLF)
                $oOL = _OL_Open()
                ShellExecuteWait($_FilePath)
                Do
                    Sleep(100)
                    $oItem = $oOL.ActiveInspector.CurrentItem
                Until @error = 0
                $oOL.ActiveInspector.WindowState = 1 ; Set the Window to minimized.
                $aProperties = _OL_ItemGet($oOL, $oItem, Default, "ReceivedTime")
                $ReceiveDate = $aProperties[1][1]
                LabelUdate("Receive Date: " & TS_Readable($ReceiveDate) & @CRLF)
                $result = $oItem.Close(1) ; Close and discard the item

                LabelUdate("Warte, bis der Zeitstempel gesetzt werden kann.")
                $WaitCount = 0
                While FileSetTime($_FilePath, $ReceiveDate) = 0
                    Sleep(200)
                    LabelUdate(".")
                    $WaitCount += 1
                    If $WaitCount > 20 Then
                        WinSetOnTop($GuiTitle, "", 0)
                        MsgBox(0, "Datei ist gesperrt", "Der Zeitstempel der Datei kann nicht angepasst werden, sie ist gesperrt." & @CRLF & _
                                "Bitte schließen sie OUTLOOK, das sollte dieses Problem beheben.")
                        $WaitCount = 0
                        WinSetOnTop($GuiTitle, "", 1)
                    EndIf
                WEnd
                LabelUdate(" fertig. (OK)" & @CRLF)
                _OL_Close($oOL)
            EndIf
        EndIf
    Else
        GUICtrlSetData($InputFile, $DragDropInfo)
        LabelUdate("*KEINE* MSG Datei: " & $input & @CRLF)
        MsgBox(0, "Keine MSG Datei", "Dies ist keine Outlook Email 'MSG' Datei.", 5)
        $resultTxt = ""
        LabelUdate("")
    EndIf


EndFunc   ;==>FixTimeStamp





Func LabelUdate($_txt)
    $resultTxt &= $_txt
    GUICtrlSetData($LabelResult, $resultTxt)
    ; ClipPut($EditResultTxt)
EndFunc   ;==>LabelUdate




Func TS_Readable($_String)
    If Not StringLen($_String) = 14 Then
        Return ("No valid Timestamp: " & $_String)
    Else
        Local $foo = StringLeft($_String, 4) ; YYYY
        $foo &= "-" & StringMid($_String, 5, 2) ; MM
        $foo &= "-" & StringMid($_String, 7, 2) ; DD
        $foo &= " " & StringMid($_String, 9, 2) ; hh
        $foo &= ":" & StringMid($_String, 11, 2) ; mm
        $foo &= ":" & StringMid($_String, 13, 2) ; ss
        Return $foo
    EndIf
EndFunc   ;==>TS_Readable

 

 

 

Regards, Rudi.


Earth is flat, pigs can fly, and Nuclear Power is SAFE!

Share this post


Link to post
Share on other sites

That's quite strange, because _OL_Open attaches to a running instance or starts a new one, whichever is needed.
What is the value of @error and @extended when Outlook is running? I assume the problem is related to _OL_Open?


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

Hi,

$oOL = _OL_Open()
                ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ' - _OL_Open) : $oOL = "' &              $oOL & '"' & @CRLF & '>Error code: ' & @error & @CRLF & _
                "@extended: " & @extended) ;### Debug Console
@@ Debug(93 - _OL_Open) : $oOL = ""
>Error code: 0
@extended: 1

Failing is just the "touch" of the "last modified" time stamp: The file is locked by OUTLOOK.EXE. As soon as I close outlook, the touch is done.

(retrieving the "receive date" from the MSG file is working fine).

I also tried to get around this by moving up the _OL_Close(), then do the "touch", no change:

LabelUdate("MSG Datei erkannt." & @CRLF)
                $oOL = _OL_Open()
                ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ' - _OL_Open) : $oOL = "' &              $oOL & '"' & @CRLF & '>Error code: ' & @error & @CRLF & _
                "@extended: " & @extended) ;### Debug Console

                ShellExecuteWait($_FilePath)
                Do
                    Sleep(100)
                    $oItem = $oOL.ActiveInspector.CurrentItem
                Until @error = 0
                $oOL.ActiveInspector.WindowState = 1 ; Set the Window to minimized.
                $aProperties = _OL_ItemGet($oOL, $oItem, Default, "ReceivedTime")
                $ReceiveDate = $aProperties[1][1]
                LabelUdate("Receive Date: " & TS_Readable($ReceiveDate) & @CRLF)
                $result = $oItem.Close(1) ; Close and discard the item
                _OL_Close($oOL)
                LabelUdate("Warte, bis der Zeitstempel gesetzt werden kann.")
                $WaitCount = 0
                While FileSetTime($_FilePath, $ReceiveDate) = 0
                    Sleep(200)
                    LabelUdate(".")
                    $WaitCount += 1
                    If $WaitCount > 20 Then
                        WinSetOnTop($GuiTitle, "", 0)
                        MsgBox(0, "Datei ist gesperrt", "Der Zeitstempel der Datei kann nicht angepasst werden, sie ist gesperrt." & @CRLF & _
                                "Bitte schließen sie OUTLOOK, das sollte dieses Problem beheben.")
                        $WaitCount = 0
                        WinSetOnTop($GuiTitle, "", 1)
                    EndIf
                WEnd

 

Regards, Rudi.


Earth is flat, pigs can fly, and Nuclear Power is SAFE!

Share this post


Link to post
Share on other sites

Maybe you could set the msg file to Read-Only before using ShellExecuteWait adn reset it to Read-Write after $oItem.Close?


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

Hi.

Very good suggestion, it's doing the trick :D

This is now a version doing what's needed: Drag-drop Outlook MSG files to the input GUI to modify the File Date (last modified) to the "received date" of the original Email Message, that was saved to a MSG file:

 

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Outfile=z:\Email-Receive-to-SaveDate.exe
#AutoIt3Wrapper_Res_Description=Zeitstempel von Outlook MSG Files im Dateisystem auf "receive date" setzen.
#AutoIt3Wrapper_Res_Fileversion=2.0.0.3
#AutoIt3Wrapper_Res_Fileversion_AutoIncrement=y
#AutoIt3Wrapper_Res_LegalCopyright=(c) 2015 by Rudolf Thilo, IT-Beratung Rudolf Thilo
#AutoIt3Wrapper_Res_SaveSource=y
#AutoIt3Wrapper_Res_Language=1031
#AutoIt3Wrapper_Run_Au3Stripper=y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <GUIConstantsEx.au3>
#include <OutlookEX.au3>
#include <WindowsConstants.au3>


If Not @Compiled Then
    Opt("trayicondebug", 1)
    Opt("trayautopause", 0)
Else
    Opt("TrayIconHide",1)
EndIf



$MsgMatch = "*.msg"

$GuiTitle = "Email MSG Dateien: Zeitstempel korrigieren"
$labelTxt = "Um das Datei-Datum von Outlook Email Dateien auf dem Server auf das Empfangsdatum zu korrigieren, diese in das weiße Feld in diesem Fenster ziehen."

$resultTxt = ""
$DragDropInfo = "Gespeicherte Email Datei(en) hier hinein ziehen"


$w = 800
$h = 500
$MyGui = GUICreate($GuiTitle, $w, $h , -1, -1, -1, $WS_EX_ACCEPTFILES) ; generally enable drag-drop for files into other GUI controls
GUICtrlCreateLabel($labelTxt, 20, 20, $w - 40, 50)
$InputFile = GUICtrlCreateInput($DragDropInfo, 20, 70, $w - 40, 40)
GUICtrlSetState(-1, $GUI_DROPACCEPTED) ; allow drag-droping files for this control, $InputFiles
GUICtrlCreateGroup("Ergebnisse", 20, 120, $w - 40, $h - 180)
$LabelResult = GUICtrlCreateLabel($resultTxt, 30, 135, $w - 55, $h - 205)
$exit = GUICtrlCreateButton("Programm beenden", $w / 2 - 60, $h - 45, 120, 30)
GUISetState()


$RegExMsg = "(?i)(^.*?\.msg$)"

While 1
    Switch GUIGetMsg()
        Case $exit, $GUI_EVENT_CLOSE
            GUIDelete($MyGui)
            MsgBox(0, "Abbruch durch Benutzer", "Bis nächstes Mal!", 3)
            Exit
    EndSwitch

    $input = GUICtrlRead($InputFile)
    If $input <> $DragDropInfo Then
        WinSetOnTop($GuiTitle, "", 1)
        GUICtrlSetState($InputFile, $GUI_DISABLE)
        $MsgFile = StringReplace($input, $DragDropInfo, "")
        If StringInStr($MsgFile, "|") Then ; da wurden mehrere Dateien reingezogen --> Array bilden
            $aMsgFile = StringSplit($MsgFile, "|", 2) ; no counter value in first element of array
            For $foo In $aMsgFile
                FixTimeStamp($foo)
            Next
        Else
            FixTimeStamp($MsgFile)
        EndIf
        WinSetOnTop($GuiTitle, "", 0)
        GUICtrlSetState($InputFile, $GUI_ENABLE)
        LabelUdate(@CRLF & "Warte auf weitere Dateien (drag-drop im Feld oben) ..." & @CRLF)
    EndIf
WEnd

Func FixTimeStamp($_FilePath)
    $resultTxt = StringTrimLeft($resultTxt, StringInStr($resultTxt, @CRLF, 0, -10))
    LabelUdate(@CRLF & "Neues Objekt: " & $_FilePath & @CRLF)
    If StringRegExp($_FilePath, $RegExMsg) Then ; das ist eine MSG Datei
        GUICtrlSetData($InputFile, $DragDropInfo)
        If FileExists($_FilePath) Then
            If StringInStr(FileGetAttrib($_FilePath), "d") Then ; das ist ein Verzeichnis
                LabelUdate("Das ist ein Verzeichnis, keine MSG Datei!" & @CRLF)
                WinSetOnTop($GuiTitle, "", 0)
                MsgBox(48, "Fehler", "Das ist ein Verzeichnis, keine MSG Datei!" & @CRLF & $_FilePath)
                WinSetOnTop($GuiTitle, "", 1)
            Else
                FileSetAttrib($_FilePath,"+r")
                LabelUdate("MSG Datei erkannt." & @CRLF)
                $oOL = _OL_Open()
                ShellExecuteWait($_FilePath)
                Do
                    Sleep(100)
                    $oItem = $oOL.ActiveInspector.CurrentItem
                Until @error = 0
                $oOL.ActiveInspector.WindowState = 1 ; Set the Window to minimized.
                $aProperties = _OL_ItemGet($oOL, $oItem, Default, "ReceivedTime")
                $ReceiveDate = $aProperties[1][1]
                LabelUdate("Receive Date: " & TS_Readable($ReceiveDate) & @CRLF)
                $result = $oItem.Close(1) ; Close and discard the item
                _OL_Close($oOL)
                LabelUdate("Warte, bis der Zeitstempel gesetzt werden kann.")
                $WaitCount = 0
                FileSetAttrib($_FilePath,"-r")
                While FileSetTime($_FilePath, $ReceiveDate) = 0
                    Sleep(200)
                    LabelUdate(".")
                    $WaitCount += 1
                    If $WaitCount > 20 Then
                        WinSetOnTop($GuiTitle, "", 0)
                        MsgBox(0, "Datei ist gesperrt", "Der Zeitstempel der Datei kann nicht angepasst werden, sie ist gesperrt." & @CRLF & _
                                "Bitte schließen sie OUTLOOK, das sollte dieses Problem beheben.")
                        $WaitCount = 0
                        WinSetOnTop($GuiTitle, "", 1)
                    EndIf
                WEnd
                LabelUdate(" fertig. (OK)" & @CRLF)
            EndIf
        EndIf
    Else
        GUICtrlSetData($InputFile, $DragDropInfo)
        LabelUdate("*KEINE* MSG Datei: " & $input & @CRLF)
        MsgBox(0, "Keine MSG Datei", "Dies ist keine Outlook Email 'MSG' Datei.", 5)
        $resultTxt = ""
        LabelUdate("")
    EndIf
EndFunc   ;==>FixTimeStamp


Func LabelUdate($_txt)
    $resultTxt &= $_txt
    GUICtrlSetData($LabelResult, $resultTxt)
    ; ClipPut($EditResultTxt)
EndFunc   ;==>LabelUdate


Func TS_Readable($_String)
    If Not StringLen($_String) = 14 Then
        Return ("No valid Timestamp: " & $_String)
    Else
        Local $foo = StringLeft($_String, 4) ; YYYY
        $foo &= "-" & StringMid($_String, 5, 2) ; MM
        $foo &= "-" & StringMid($_String, 7, 2) ; DD
        $foo &= " " & StringMid($_String, 9, 2) ; hh
        $foo &= ":" & StringMid($_String, 11, 2) ; mm
        $foo &= ":" & StringMid($_String, 13, 2) ; ss
        Return $foo
    EndIf
EndFunc   ;==>TS_Readable

Regards, Rudi


Earth is flat, pigs can fly, and Nuclear Power is SAFE!

Share this post


Link to post
Share on other sites

Glad the problems could be solved and you've got a perfect app now :)


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now