php - imap - moving emails on antoher account

2019-04-02 17:27发布

I am working on a script that downloads emails and stores them in a db, I usually receive thousands of emails on this account, once downloaded the mails are deleted.

Being paranoic, I want to have at least one month backup of my emails, but I cannot clutter my main mailbox address leaving them in there.

So i need to move the mails (via php code) from one mailbox to another. I came up with this solution that uses imap_append(). This solution, however recreates the email, and does not really move it.

Do you have any suggestions or alternative ways of doing this?

Remember: it must be done in php, because I need to integrate it in my readmail script.

I have already seen this thread where a fetchmail solution was proposed

Here follows the code I wrote for this task

<?php
/**
* Conn params
*/

$fromMboxServerPath = "{imap.from.server/notls/imap:143}";
$fromMboxMailboxPath = "INBOX";
$fromMboxMailAddress = "login";
$fromMboxMailPass = "pass";


$toMboxServerPath = "{imap.to.server/notls/imap:143}";
$toMboxMailboxPath = "INBOX";
$toMboxMailAddress = "login";
$toMboxMailPass = "pass";

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

$fetchStartSeq = 1;
$fetchEndSeq = 10;

function myLog($str)
{
    echo "Log [".date('Y-m-d H:i:s')."]: $str\n";
}

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);
    $fb = imap_body($fromMbox, $i);
    $message = $fh.$fb;

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

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

    /**
     * We do some logging
     */

    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]");

    /**
     * Here you do whaterver you need with your email
     */

    /**
     * Backup email
     */
    if (!($ret = imap_append($toMbox,$toMboxServerPath.$toMboxMailboxPath,$message))) 
    {
        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");

?>

标签: php email imap
3条回答
聊天终结者
2楼-- · 2019-04-02 17:43

First, IMAP does not have a MOVE command only copy but even if it did you can copy from one IMAP server to another directly.

Why not use a subfolder in the account for backups. Download them to your local machine then COPY them to the subfolder and then DELETE them from the INBOX.

COPY and DELETE are imap server side commands so they don't have to leave the server to do the "move"

If both accounts are on the same server there is another option, allow access to the backup account's INBOX to the primary account user. Then you can use server side copy/delete to move it to the backup folder.

Not all IMAP servers allow for shared folders.

php does have a imap_move function but I assume it does a copy/delete.

查看更多
Ridiculous、
3楼-- · 2019-04-02 17:48

I don't know any other solution like PHP.

But for your code and testing you should use:

$fromMboxServerPath = "{imap.from.server/notls/imap/readonly:143}"; //ReadOnly

in imap_append() you should give the date from emailheader. see PHP Manual: http://php.net/manual/en/function.imap-append.php

after that you will have a 1to1 copy of your mail in the target IMAP-Server.

查看更多
做自己的国王
4楼-- · 2019-04-02 17:58

Why separate account and all the hassle that will be involved? Can't you either

a) backup the mail account using standard backup tools like, eg. rdiff-backup?

b) back them up in the db?

or even

c) create an alias so that emails go to both accounts and you have different criteria for removing mails from both accounts (ie. keep them for one more month in the backup account)

查看更多
登录 后发表回答