IMAP Migration PHP Script

So after a bit of digging I was able to complete a working IMAP mailbox-to-mailbox migration script to help move accounts between servers. A lot of time and effort will be saved, as it is run directly on the server rather than linking your mail client to two accounts and transferring it using drag and drop. You can use it to sync your emails using IMAP, however it won’t check if emails already exist before transferring, so you will end up with duplicates.

It uses imap_append (part of php) including the 5th date variable so there is a 1:1 copy of your email between both servers. The only downside to it at this point is script timeouts and running out of memory on the server, as it uses quite a lot. If you limit it to 1000 emails at a time it has no issues.

Here’s the PHP script if you want to try it out:

<?php

$fromMboxServerPath = “{servera.com/notls/imap:143}”;
$fromMboxMailboxPath = “INBOX”;

$toMboxServerPath = “{serverb.com/notls/imap:143}”;
$toMboxMailboxPath = “INBOX”;

$fromMboxMailAddress = “username”;
$fromMboxMailPass = “password”;

$toMboxMailAddress = “username”;
$toMboxMailPass = “password”;

$fromMboxConnStr = $fromMboxServerPath.$fromMboxMailboxPath;
$toMboxConnStr = $toMboxServerPath.$toMboxMailboxPath;

//Increment these (ie: 1001 to 2000) to continue transferring
$fetchStartSeq = 1;
$fetchEndSeq = 1000;

function myLog($str)
{
echo “Log [“.date(‘Y-m-d H:i:s’).”]: $str\n<BR>”;
}

myLog(“Connecting to mailbox”);

function mboxConn($connstr,$addr,$pass)
{
if(!($mbox = @imap_open($connstr, $addr, $pass)))
{
myLog(“Error: “.imap_last_error());
die;
}
else
{
myLog(“Connected to: $addr $connstr”);
return $mbox;
}
}

function mboxCheck($mbox)
{
if(!($mbox_data = imap_check($mbox)))
{
myLog(“Error: “.imap_last_error());
die;
}
else
{
myLog(“Mailbox check “.$mbox_data->Mailbox.” OK”);
myLog($mbox_data->Nmsgs.” messages present”);
return $mbox_data->Nmsgs;
}
}

$fromMbox = mboxConn($fromMboxConnStr, $fromMboxMailAddress, $fromMboxMailPass);
$toMbox = mboxConn($toMboxConnStr, $toMboxMailAddress, $toMboxMailPass);

$fromMboxCount = mboxCheck($fromMbox);
$toMboxCount = mboxCheck($toMbox);

/**
* Loop on mails
*/

$fetchStartUID = imap_uid($fromMbox,$fetchStartSeq);
if ($fromMboxCount < $fetchEndSeq)
{
$fetchEndSeq = $fromMboxCount;
}
$fetchEndUID = imap_uid($fromMbox,$fetchEndSeq);

/**
* Loop on mails
*/

myLog(“Do stuff and backup from UID [$fetchStartUID] to UID [$fetchEndUID]”);

for ($i=$fetchStartSeq;$i<=$fetchEndSeq;$i++)
{
$pfx = “Msg #$i : “;
$h = imap_header($fromMbox, $i);
$fh = imap_fetchheader($fromMbox, $i);
$headerinfo = imap_headerinfo($fromMbox, $i);
$internal_date=date(‘d-M-Y H:i:s O’,$headerinfo->udate); //important!
$fb = imap_body($fromMbox, $i);
$message = $fh.$fb;

$msgUID = imap_uid($fromMbox,$i);

$struct = imap_fetchstructure ($fromMbox, $i);

/**
* We do some logging
*/

myLog($pfx.”Date: [“.$internal_date.”]”);
myLog($pfx.”UID [“.$msgUID.”] SEQ [“.imap_msgno($fromMbox,$msgUID).”] Flags: [“. $h->Unseen . $h->Recent . $h->Deleted . $h->Answered . $h->Draft . $h->Flagged.”]”);
myLog($pfx.”From: [“. htmlspecialchars($h->fromaddress) . “] To: [“.htmlspecialchars($h->toaddress).”]”);
myLog($pfx.”Subject: [$h->subject]”);

/**
* Transfer email using imap_append – All will be marked as read using 4th variable SEEN
*/
if (!($ret = imap_append($toMbox,$toMboxServerPath.$toMboxMailboxPath,$message,”\SEEN”,$internal_date)))
{
myLog(“Error: “.imap_last_error());
die;
}
else
{
myLog(“everything ok, mail [$fetchStartUID:$fetchEndUID] downloaded and moved in $newMailboxNameMOVE”);
}
}

/**
* End
*/

imap_close($fromMbox);
imap_close($toMbox);

myLog(“Connection closed”);

?>

Leave a Reply

Your email address will not be published. Required fields are marked *