Question
Eduard Lebedyuk · Dec 16, 2015

Sync emails from mailbox to Cache

Hello.

I want to store a mailbox in Caché, persistently.

Does anyone have some code for downloading all messages from mailbox into Caché? And maybe automatic syncing after download? I know, there is  %Net.POP3 but maybe someone has already done that.

 

Thank you.

1
0 1,140
Discussion (12)1
Log in or sign up to continue

Hi Eduard,

I wanted to do that last year but I never got to start the project.

My use case was to export all messages from an Outlook format. I remember finding some script or some OSS somewhere that seemed interesting. I think that aside the 1st load the syncing is the true issue.

Do you have to go straight to the POP server?

Hi, Luca.

IMAP would be better than POP I suppose.

I agree on IMAP Eduard. I never understood why it never took off as POP did... I guess Microsoft ;-)

So, can we help each other out here?

Mine was and is just a private project.... it sounds like you have to interface with an IMAP or POP server...

Yes, I'm searching for a ready code downloading from Gmail etc. Or at least code connecting to the server.

ClassMethod GmailAsPOP3() As %Net.POP3
{

  Set server=##class(%Net.POP3).%New()
  
  Set server.port=995

  //just in case we plan to fetch any messages
  //that have attachments
  Set server.StoreAttachToFile=1
  Set server.StoreInlineToFile=1
  Set server.AttachDir="c:\DOWNLOADS\"
  

  Set servername="pop.gmail.com"
  Set server.UseSTARTTLS=1
  Set server.SSLConfiguration = "GMail" //any empty enabled client SSL/TLS config

  Set user="mail@gmail.com"
  Set pass="pass"
  
  Set status=server.Connect(servername,user,pass)
  If $$$ISERR(status)
  {
    Do $System.Status.DisplayError(status)
    Quit $$$ERROR()
    }
  Quit server
}

 

It returns this error:ERROR #6013: Unable to make TCP/IP connection to mail server.  An earlier connection may not have been closed. [zConnectPort+39^%Net.POP3.1:EMAIL]

I did a project similar to this using %Net.POP3 a few years back (internal ref: ISCX2452), but it's part of a much larger application, so the exact code probably would not be very useful.

The general pattern for using %Net.POP3 is:

 set tSC = server.Connect(servername,username,password)
 set tSC = server.GetMailBoxStatus(.numberOfMessages)
 for i=1:1:numberOfMessages {
  set tSC = server.Fetch(i,.msg)
  //msg is a %Net.MailMessage
  //optional: set tSC = server.DeleteMessage(i)
 }
 //IMPORTANT! QuitAndCommit() or QuitAndRollback()
 set tSC = server.QuitAndCommit()


Add your own status-checking, try/catch, etc. One important caution: always be careful to clean up the connection when you're done, with either QuitAndRollback or QuitAndCommit. This might be the cause of the error you noted in your last comment - an open connection could be left over from before, blocking additional connections. I think terminating the process will fix this. (I remember this causing all sorts of trouble/confusion on my old project.)

As a side note: if your application/use case is running on Ensemble, EnsLib.EMail.InboundAdapter will do a lot of the hard work for you. See for reference: http://docs.intersystems.com/ens20152/csp/docbook/DocBook.UI.Page.cls?KE...

This adapter will delete successfully-processed e-mails. From a "syncing" perspective this keeps things simple. If you don't want the messages deleted, a simple workaround might be to subclass EnsLib.EMail.InboundAdapter and %Net.POP3, override DeleteMessage to make it a no-op in the %Net.POP3 subclass, and override the adapter's MailServer property to use your %Net.POP3 subclass. (This would be a bit less messy than overriding OnTask.)

I've been looking but I can't find POP specific examples....

So once we have letters database may be we can try iKnow on it?

Hi, I am building an Email client in Cache, and succeeded to send out emails (smpt)

On downloading emails I have tested the pop3 sample from the InterSystems documentation:

ClassMethod YPOPsAsPOP3() As %Net.POP3
{
  //Sample from InterSystems
  Set server=##class(%Net.POP3).%New()
  
  //YPOPs uses the default port
  //but let's set it anyway
  Set server.port=110

  //just in case we plan to fetch any messages
  //that have attachments
  //Set server.StoreAttachToFile=1
  //Set server.StoreInlineToFile=1
  //Set server.AttachDir="c:\DOWNLOADS\"
  
  //local host acts as the server
  Set servername="mail.xxxxxxxx.nl"
  //YPOPs works with a Yahoo email account
  Set user="marco@xxxx.nl"
  Set pass="XXXXXXXX"
  
  Set status=server.Connect(servername,user,pass)
  
  If $$$ISERR(status)
  {

    Do $System.Status.DisplayError(status)
    Quit $$$ERROR()
    }
    
    Do ##class(ZenMail.MailFunctions).ShowMailbox(server)
    Do ##class(ZenMail.MailFunctions).FetchMailbox(server)
    Do ##class(ZenMail.MailFunctions).ShowMsgInfo(1)
    
  Quit server
}

I succeed to get information out of my mailbox however with the following error(s):

and at the end:

has anybody an idea how to solve this? for me this error is a bit a flurry....

I would like to invite people to work on a working example with complete working code base rather than open answers

which do not contribute to a completed working topic.

Thanks in advance!

Hi,

Just curious if there's  a resolution to unable to connect TCP/IP error, i'm trying to fetch an attachment file from an exchange server. Validated POP3 is enabled on exchange, able to telnet to the port from ensemble but failed when trying to use 'Class' routine and i'm thinking of using EnsLib.EMail.InboundAdapter but will this method be able to fetch an attachment file?  Thanks for your help.