UIDLManager.SyncUIDL Method


Removes UIDL that is not existent on server from local UIDL file.
This method is obsoleted by SyncUIDLEX

[Visual Basic 6.0]
Public Sub SyncUIDL( oServer As MailServer, _
infos() As MailInfo _
)
[Visual C++]
public: SyncUIDL(
MailServer* oServer,
VARIANT infos
);

Parameters

oServer
The current mail server instance.
infos
MailInfo array existed on mail server.

This method removes UIDL that is not existent on server from local UIDL file.

Remarks

Sometimes the developers want to leave a copy of email on the POP3/IMAP4/Exchange server for backup, so they don't delete the email after the email was received. The common issue is how to detect if the email has been retrieved by the application already, otherwise, all the emails on the server will be retrieved again and again. In this case, we should use the Unique Identifier (UIDL) to avoid to receive the same email more than once.

Using Unique Identifier (UIDL)

The mail server assigns an unique identifier for every email in the same account. You can get the UIDL for every email by MailInfo.UIDL property. To avoid to receive the same email twice, the best way is storing the UIDL of email retrieved to a text file or database. Next time before you retrieve the email, compare your local uidl list with remote uidl. If this uidl exists in your local uidl list, then you don't receive it, otherwise you should receive it.

Difference with UIDL in POP3/IMAP4/Exchange Web Service/WebDAV

UIDL is always unique in IMAP4 and it is always increasing integer. UIDL in POP3 can be any valid asc-ii characters, and the UIDL may be reused by POP3 server if the email with the UIDL has been deleted from the server, so we suggest that you should remove the uidl from your local uidl list if the uidl is no longer existed on the POP3 server. UIDL is also unique in Exchange Web Service/WebDAV, but the UIDL is string but not integer. Every email has a unique identifier (UIDL) on IMAP4 server. It is a 32bit integer and it is always unique in your email account life time. So we can use the integer as file name to identify if the email has been downloaded. There is a little bit different in POP3 server. The UIDL is only unique in the email life time. That means if the email was deleted from the server, other email can use the old unique identifier. Another problem is: UIDL in POP3 server can be any number or characters, so we cannot use UIDL as the file name, because UIDL may contain invalid characters for file name. For Exchange Web Service/WebDAV, although the UIDL is always unique in your email account, but UIDL may also contain invalid characters for file name.

Total Solution

UIDLManager provides an easy way to maintain UIDL between your server and your local client. How does it work? It stores UIDL collection to a local disk file and you can use this object to add, remove and search UIDL with this local file.

UIDL File Format

With UIDLManager, you can use any file name as the UIDL local file, but we suggest that you use different UIDL file for different email account. In the UIDL file, each line presents a UIDL information.

"mailserver#user#protocol","UIDL","Local File Name","Download Date Time","Flags"
"mailserver#user#protocol","UIDL1","Local File Name1","Download Date Time","Flags"
        

You can use UIDLManager to record the UIDL of the email that you have downloaded; you can also associate the local file name and flags to UIDLItem object. Then you can use UIDLManager to detect if the email has been downloaded, when it has been downloaded. If it has been downloaded, what local file it has saved to.

Example

[[Visual Basic 6.0, VBScript, Visual C++] The following example demonstrates how To retrieve email with EAGetMail POP3 & IMAP Component, but it doesn't demonstrates the events and mail parsing usage. To get the full samples of EAGetMail, please refer to Samples section.

[Visual Basic 6.0]
Public Sub ReceiveMail( _
ByVal sServer As String, _
ByVal sUserName As String, _
ByVal sPassword As String, _
ByVal bSSLConnection As Boolean, _
ByVal bLeaveCopy)
    
    Const MailServerPop3 = 0
    Const MailServerImap4 = 1
    Const MailServerEWS = 2
    Const MailServerDAV = 3

    Dim oClient As New EAGetMailObjLib.MailClient
    oClient.LicenseCode = "TryIt"
    
    'bLeaveCopy = True will leave a copy of message on the server
    'bLeaveCopy = False will delete the email after the download is finished.

    'To receive email from imap4 server, please change
    'MailServerPop3 to MailServerImap4 to MailServer.Protocol

    'To receive email with Exchange Web Service, please change
    'MailServerPop3 to MailServerEWS to MailServer.Protocol

    'To receive email with Exchange WebDAV, please change
    'MailServerPop3 to MailServerDAV to MailServer.Protocol

    'Exchange Server supports POP3/IMAP4 protocol as well, but in Exchange 2007
    'or later version, POP3/IMAP4 service is disabled by default. If you don't want to use POP3/IMAP4
    'to download email from Exchange Server, you can use Exchange Web Service(Exchange 2007/2010 or
    'later version) or WebDAV(Exchange 2000/2003) protocol.
    
    'For Exchange Web Service/WebDAV, please ignore 
    'Port property. But for Exchange Web Service, please set SSLConnection to True

    Dim oServer As New EAGetMailObjLib.MailServer
    oServer.Server = sServer
    oServer.User = sUserName
    oServer.Password = sPassword
    oServer.SSLConnection = bSSLConnection
    oServer.Protocol = MailServerPop3
    
    'By default, the pop3 port is 110, imap4 port is 143,
    'the pop3 ssl port is 995, imap4 ssl port is 993
    'you can also change the port like this
    'oServer.Port = 110
    
    If oServer.Protocol = MailServerImap4 Then
        If oServer.SSLConnection Then
            oServer.Port = 993 'SSL IMAP4
        Else
            oServer.Port = 143 'IMAP4 normal
        End If
    Else
        If oServer.SSLConnection Then
            oServer.Port = 995 'SSL POP3
        Else
            oServer.Port = 110 'POP3 normal
        End If
    End If
    
    ' UIDL is the identifier of every email on POP3/IMAP4/Exchange server, to avoid retrieve
    ' the same email from server more than once, we record the email UIDL retrieved every time
    ' if you delete the email from server every time and not to leave a copy of email on
    ' the server, then please remove all the function about uidl.
    ' UIDLManager wraps the function to write/read uidl record from a text file.
    Dim oUIDLManager As New EAGetMailObjLib.UIDLManager
    
    ' Create a folder to store uidl file and email files
    Dim localfolder As String
    localfolder = "d:\mailfolder"
    Dim uidlfile As String
    uidlfile = "d:\mailfolder\uidl.txt"
    
    Dim oTools As New EAGetMailObjLib.Tools
    If Not oTools.ExistFile(localfolder) Then
        oTools.CreateFolder localfolder
    End If
    
    On Error GoTo ErrorHandle
    
        ' Load existed uidl records to UIDLManager
        oUIDLManager.Load uidlfile
        
        oClient.Connect oServer
        Dim infos
        infos = oClient.GetMailInfos()
        
        ' Remove the local uidl which is not existed on the server.
        oUIDLManager.SyncUIDL oServer, infos
        oUIDLManager.Update


        Dim i, Count
        Count = UBound(infos)
        For i = LBound(infos) To Count
            Dim info As EAGetMailObjLib.MailInfo
            Set info = infos(i)
            
            Debug.Print "UIDL: " & info.UIDL
            
            'This email has not been downloaded
            If oUIDLManager.FindUIDL(oServer, info.UIDL) Is Nothing Then
           
                Dim fileName As String
                'generate a random file name by current local datetime,
                'you can use your method to generate the filename if you do not like it
                Dim shortName As String
                shortName = oTools.GenFileName(i) & ".eml"
                fileName = localfolder & "\" & shortName
               
               
                Dim oMail As EAGetMailObjLib.Mail
                Set oMail = oClient.GetMail(info)
                'Save mail to local disk
                oMail.SaveAs fileName, True
                
                If bLeaveCopy Then
                    'add the email uidl to uidl file to avoid we retrieve it next time.
                    oUIDLManager.AddUIDL oServer, info.UIDL, shortName
                End If
            End If
        Next

        If Not bLeaveCopy Then
            For i = LBound(infos) To Count
                 oClient.Delete infos(i)
                ' Remove UIDL from local uidl file.
                oUIDLManager.RemoveUIDL oServer, infos(i).UIDL
            Next
        End If

        ' Delete method just mark the email as deleted,
        ' Quit method expunge the emails from server permanently.
        oClient.Quit
        oUIDLManager.Update
        Exit Sub
ErrorHandle:
        'Error handle
        MsgBox Err.Description
        oUIDLManager.Update
        oClient.Close
End Sub


[VBScript] Public Sub ReceiveMail( _ ByVal sServer As String, _ ByVal sUserName As String, _ ByVal sPassword As String, _ ByVal bSSLConnection As Boolean, _ ByVal bLeaveCopy) Const MailServerPop3 = 0 Const MailServerImap4 = 1 Const MailServerEWS = 2 Const MailServerDAV = 3 Dim oClient Set oClient = CreateObject("EAGetMailObj.MailClient") oClient.LicenseCode = "TryIt" 'bLeaveCopy = True will leave a copy of message on the server 'bLeaveCopy = False will delete the email after the download is finished. 'To receive email from imap4 server, please change 'MailServerPop3 to MailServerImap4 to MailServer.Protocol 'To receive email with Exchange Web Service, please change 'MailServerPop3 to MailServerEWS to MailServer.Protocol 'To receive email with Exchange WebDAV, please change 'MailServerPop3 to MailServerDAV to MailServer.Protocol 'Exchange Server supports POP3/IMAP4 protocol as well, but in Exchange 2007 'or later version, POP3/IMAP4 service is disabled by default. If you don't want to use POP3/IMAP4 'to download email from Exchange Server, you can use Exchange Web Service(Exchange 2007/2010 or 'later version) or WebDAV(Exchange 2000/2003) protocol. 'For Exchange Web Service/WebDAV, please ignore 'Port property. But for Exchange Web Service, please set SSLConnection to True Dim oServer Set oServer = CreateObject("EAGetMailObj.MailServer") oServer.Server = sServer oServer.User = sUserName oServer.Password = sPassword oServer.SSLConnection = bSSLConnection oServer.Protocol = MailServerPop3 'By default, the pop3 port is 110, imap4 port is 143, 'the pop3 ssl port is 995, imap4 ssl port is 993 'you can also change the port like this 'oServer.Port = 110 If oServer.Protocol = MailServerImap4 Then If oServer.SSLConnection Then oServer.Port = 993 'SSL IMAP4 Else oServer.Port = 143 'IMAP4 normal End If Else If oServer.SSLConnection Then oServer.Port = 995 'SSL POP3 Else oServer.Port = 110 'POP3 normal End If End If ' UIDL is the identifier of every email on POP3/IMAP4/Exchange server, to avoid retrieve ' the same email from server more than once, we record the email UIDL retrieved every time ' if you delete the email from server every time and not to leave a copy of email on ' the server, then please remove all the function about uidl. ' UIDLManager wraps the function to write/read uidl record from a text file. Dim oUIDLManager Set oUIDLManager = CreateObject("EAGetMailObj.UIDLManager") ' Create a folder to store uidl file and email files Dim localfolder localfolder = "d:\mailfolder" Dim uidlfile uidlfile = "d:\mailfolder\uidl.txt" Dim oTools Set oTools = CreateObject("EAGetMailObj.Tools") If Not oTools.ExistFile(localfolder) Then oTools.CreateFolder localfolder End If ' Load existed uidl records to UIDLManager oUIDLManager.Load uidlfile oClient.Connect oServer Dim infos infos = oClient.GetMailInfos() ' Remove the local uidl which is not existed on the server. oUIDLManager.SyncUIDL oServer, infos oUIDLManager.Update Dim i, Count Count = UBound(infos) For i = LBound(infos) To Count Dim info Set info = infos(i) WScript.Echo "UIDL: " & info.UIDL 'This email has not been downloaded If oUIDLManager.FindUIDL(oServer, info.UIDL) Is Nothing Then Dim fileName 'generate a random file name by current local datetime, 'you can use your method to generate the filename if you do not like it Dim shortName shortName = oTools.GenFileName(i) & ".eml" fileName = localfolder & "\" & shortName Dim oMail Set oMail = oClient.GetMail(info) 'Save mail to local disk oMail.SaveAs fileName, True If bLeaveCopy Then 'add the email uidl to uidl file to avoid we retrieve it next time. oUIDLManager.AddUIDL oServer, info.UIDL, shortName End If End If Next If Not bLeaveCopy Then For i = LBound(infos) To Count oClient.Delete infos(i) ' Remove UIDL from local uidl file. oUIDLManager.RemoveUIDL oServer, infos(i).UIDL Next End If ' Delete method just mark the email as deleted, ' Quit method expunge the emails from server permanently. oClient.Quit oUIDLManager.Update End Sub
[Visual C++] #include "stdafx.h" #include <windows.h> #include "eagetmailobj.tlh" using namespace EAGetMailObjLib; void ReceiveMail( LPCTSTR sServer, LPCTSTR sUserName, LPCTSTR sPassword, bool bSSLConnection, bool bLeaveCopy) { ::CoInitialize(NULL); const int MailServerPop3 = 0; const int MailServerImap4 = 1; const int MailServerEWS = 2; const int MailServerDAV = 3; try { IMailClientPtr oClient; oClient.CreateInstance(__uuidof(EAGetMailObjLib::MailClient)); IMailServerPtr oServer; oServer.CreateInstance(__uuidof(EAGetMailObjLib::MailServer)); oClient->LicenseCode = _T("TryIt"); oServer->Server = sServer; oServer->User = sUserName; oServer->Password = sPassword; INT nProtocol = MailServerPop3; //bLeaveCopy = true will leave a copy of message on the server //bLeaveCopy = false will delete the email after the download is finished. //To receive email from imap4 server, please change //MailServerPop3 to MailServerImap4 in MailServer constructor //To receive email with Exchange Web Service, please change //MailServerPop3 to MailServerEWS to MailServer.Protocol //To receive email with Exchange WebDAV, please change //MailServerPop3 to MailServerDAV to MailServer.Protocol //Exchange Server supports POP3/IMAP4 protocol as well, but in Exchange 2007 //or later version, POP3/IMAP4 service is disabled by default. If you don't want to use POP3/IMAP4 //to download email from Exchange Server, you can use Exchange Web Service(Exchange 2007/2010 or //later version) or WebDAV(Exchange 2000/2003) protocol. //For Exchange Web Service/WebDAV, please ignore //Port property. But for Exchange Web Service, please set SSLConnection to True oServer->Protocol = nProtocol; if(nProtocol == MailServerPop3) { if(bSSLConnection) { oServer->Port = 995; oServer->SSLConnection = VARIANT_TRUE; } else { oServer->Port = 110; } } else { if(bSSLConnection) { oServer->Port = 993; oServer->SSLConnection = VARIANT_TRUE; } else { oServer->Port = 143; } } // UIDL is the identifier of every email on POP3/IMAP4/Exchange server, to avoid retrieve // the same email from server more than once, we record the email UIDL retrieved every time // if you delete the email from server every time and not to leave a copy of email on // the server, then please remove all the function about uidl. // UIDLManager wraps the function to write/read uidl record from a text file. IUIDLManagerPtr oUIDLManager; oUIDLManager.CreateInstance(__uuidof(EAGetMailObjLib::UIDLManager)); IToolsPtr oTools; oTools.CreateInstance(__uuidof(EAGetMailObjLib::Tools)); // Create a folder to store uidl file and email files LPCTSTR pszFolder = _T("d:\\mailfolder"); LPCTSTR pszUIDLFile = _T("d:\\mailfolder\\uidl.txt"); if( oTools->ExistFile(pszFolder) == VARIANT_FALSE) { oTools->CreateFolder(pszFolder); } // Load existed UIDL records to UIDLManager oUIDLManager->Load(pszUIDLFile); oClient->Connect(oServer); _variant_t arInfo = oClient->GetMailInfos(); // Remove the local uidl which is not existed on the server. oUIDLManager->SyncUIDL(oServer, arInfo); oUIDLManager->Update(); SAFEARRAY *psa = arInfo.parray; long LBound = 0, UBound = 0; SafeArrayGetLBound(psa, 1, &LBound); SafeArrayGetUBound(psa, 1, &UBound); INT count = UBound-LBound+1; for(long i = LBound; i <= UBound; i++) { _variant_t vtInfo; SafeArrayGetElement(psa, &i, &vtInfo); IMailInfoPtr pInfo; vtInfo.pdispVal->QueryInterface(__uuidof(IMailInfo), (void**)&pInfo); _tprintf(_T("UIDL: %s\r\n"), (TCHAR*)pInfo->UIDL); IUIDLItemPtr oUIDLItem = oUIDLManager->FindUIDL(oServer, pInfo->UIDL); if(oUIDLItem != NULL) { // this email has been downloaded before. continue; } // this email has not been downloaded before. IMailPtr oMail = oClient->GetMail(pInfo); TCHAR fileName[MAX_PATH+1]; memset( fileName, 0, sizeof(fileName)); SYSTEMTIME curtm; ::GetLocalTime(&curtm); // generate a random file name by current local datetime, // you can use your method to generate the filename if you do not like it ::wsprintf( fileName, _T("%04d%02d%02d%02d%02d%02d%03d%d.eml"), curtm.wYear, curtm.wMonth, curtm.wDay, curtm.wHour, curtm.wMinute, curtm.wSecond, curtm.wMilliseconds, i); TCHAR fullPath[MAX_PATH+1]; memset( fullPath, 0, sizeof(fullPath)); ::wsprintf(fullPath, _T("%s\\%s"), pszFolder, fileName); oMail->SaveAs(fullPath, VARIANT_TRUE); oMail.Release(); if(bLeaveCopy) { // Add the email uidl to uidl file to avoid we retrieve it next time. oUIDLManager->AddUIDL( oServer, pInfo->UIDL, (const TCHAR*)fileName); } } if(!bLeaveCopy) { for(long i = LBound; i <= UBound; i++) { _variant_t vtInfo; SafeArrayGetElement(psa, &i, &vtInfo); IMailInfoPtr pInfo; vtInfo.pdispVal->QueryInterface(__uuidof(IMailInfo), (void**)&pInfo); oClient->Delete(pInfo); // Remove UIDL from local uidl file. oUIDLManager->RemoveUIDL(oServer, pInfo->UIDL); } } // Delete method just mark the email as deleted, // Quit method expunge the emails from server permanently. arInfo.Clear(); oUIDLManager->Update(); oClient->Quit(); } catch(_com_error &ep) { _tprintf(_T("ERROR: %s\r\n"), (TCHAR*)ep.Description()); } ::CoUninitialize(); }

See Also

MailInfo.UIDL Property

Online Tutorials

Using UIDL Function to Mark the Email has been downloaded/read in VB6 - Tutorial
Using UIDL Function to Mark the Email has been downloaded/read in Delphi - Tutorial
Using UIDL Function to Mark the Email has been downloaded/read VC++ - Tutorial