скрипт для переноса электронной почты из одного ящика в другой
Скрипт максимально простой, написан на php, так же потребуется модуль php-imap, работает из командной строки любого устройства (сервера). Принцип простой, скрипт подключается к исходному ящику по протоколу IMAP сканирует структуру почтовых папок, подключается к целевому ящику IMAP, воссоздаёт папки которых нет и загружает в них письма. Опционально может создать структуру папок локально и скачать в них письма в формате eml.
<?php
//папка, куда будет сохраняться структура ящика с письмами
$path_to_mail = 'boxes';
//сохранять локально копию ящика
$save_local_copy = 0;
//декодировать имя папки или нет для локальной копии
$decode_folder_name = 1;
//данные ящика откуда переезжаем (например яндекс)
$source_server = 'imap.yandex.ru';
$source_port = '993';
$source_user = '{user}@{domain}.ru';
$source_pass = 'P@$$word';
//данные ящика куда переезжаем
$target_server = 'mail.{domain}.ru';
$target_port = '993';
$target_user = '{user}@{domain}.ru';
$target_pass = 'P@$$word';
function check_folder_exist($folders_list, $check_folder_name) {
$fl_exist = false;
foreach ($folders_list as $val) {
if ($val->name == $check_folder_name) {
$fl_exist = true;
}
}
return $fl_exist;
}
$path_to_mail .= DIRECTORY_SEPARATOR.$source_user.DIRECTORY_SEPARATOR;
$source_server_str = "{".$source_server.":".$source_port."/imap/ssl}";
$source_mbox = imap_open($source_server_str,$source_user,$source_pass)
or die("can't connect: " . imap_last_error());
$target_server_str = "{".$target_server.":".$target_port."/imap/ssl}";
$target_mbox = imap_open($target_server_str,$target_user,$target_pass)
or die("can't connect: " . imap_last_error());
$target_list = imap_getmailboxes($target_mbox, $target_server_str, "*");
if (is_array($target_list)) {
foreach ($target_list as $key => $val) {
$folder_name = str_replace($target_server_str,'',$val->name);
$target_delimiter = $val->delimiter;
}
} else {
echo "imap_getmailboxes failed: ".imap_last_error()."\n";
}
$source_list = imap_getmailboxes($source_mbox, $source_server_str, "*");
if (is_array($source_list)) {
foreach ($source_list as $key => $val) {
$source_full_folder_name = $val->name;
$source_delimiter = $val->delimiter;
$con=imap_open($source_full_folder_name, $source_user, $source_pass);
$number_msg=imap_num_msg($con);
$folder_name = str_replace($source_server_str,'',$source_full_folder_name);
if ($decode_folder_name) {
$current_folder_name = mb_convert_encoding($folder_name, "UTF8", "UTF7-IMAP");
} else {
$current_folder_name = $folder_name;
}
$full_new_folder_name = $target_server_str.str_replace($source_delimiter,$target_delimiter,$folder_name);
echo $full_new_folder_name."\n";
if (!(check_folder_exist($target_list, $full_new_folder_name))) {
echo 'папка "'.mb_convert_encoding($folder_name, "UTF8", "UTF7-IMAP").'" отсутствует на сервере, создаём'."\n";
imap_createmailbox($target_mbox, $full_new_folder_name);
}
if ((!file_exists($path_to_mail.str_replace($source_delimiter,DIRECTORY_SEPARATOR,$current_folder_name))) and ($save_local_copy)) {
mkdir($path_to_mail.str_replace($source_delimiter,DIRECTORY_SEPARATOR,$current_folder_name), 0777, true);
}
echo mb_convert_encoding($folder_name, "UTF8", "UTF7-IMAP").": ";
echo $number_msg."\n";
for ($i = 1; $i <= $number_msg; $i++) {
if (!imap_ping($con)) {
// если вдруг связь первалась, восстанавливаем
echo "$i ой, reconnect $source_server\n";
$i--;
$con=imap_open($val->name, $source_user, $source_pass);
}
if (!imap_ping($target_mbox)) {
// если вдруг связь первалась, восстанавливаем
echo "$i ой, reconnect $target_server\n";
$target_mbox = imap_open($target_server_str,$target_user,$target_pass);
}
echo ".";
$headers = imap_fetchheader($con, $i, FT_PREFETCHTEXT);
$body = imap_body($con, $i);
imap_append($target_mbox, $full_new_folder_name, $headers."\n\n".$body,"\\Seen");
if ($save_local_copy) {
file_put_contents($path_to_mail.str_replace($val->delimiter,DIRECTORY_SEPARATOR,$current_folder_name).DIRECTORY_SEPARATOR.str_pad($i, 8, "0", STR_PAD_LEFT).".eml", $headers."\n\n".$body);
}
}
echo "\n";
imap_close($con);
}
} else {
echo "imap_getmailboxes failed: ".imap_last_error()."\n";
}
imap_close($source_mbox);
imap_close($target_mbox);
?>
$path_to_mail — относительный путь к папке, где будет храниться локальная копия ящика, актуально когда «$save_local_copy = 1»
$save_local_copy = 1 будет сохраняться локальная копия писем на жёстком диске, соответственно, если «0» — не будет
$decode_folder_name = 1 имена папок будут декодированы в нормальный вид, если «0» — то будет использован формат UTF7, как они хранятся на сервере.
Все письма, которые будут перенесены в новый ящик получат статус прочитанных, извините, я не заморачивался с перенесением флагов.
Перед прочтением сообщения пингуется соединение с сервером IMAP, в случае его обрыва — соединение восстанавливается. Замедление совсем небольшое, зато надёжность вырастает многократно.
Учитываются разделители вложенности папок (например у яндекса это «|», в iRedMail «/»).
Копирование писем допускается один раз, если вы прервёте процесс и запустите снова, часть сообщений задублируется.