Вы здесь

Миграция с Mailbox на CyrusIMAP

Перенос почтовых ящиков

Скрипт для создания пустых почтовых ящиков на основе информации в /etc/passwd

#!/usr/bin/perl -w
#
# Written by Wil Cooley <wcooley@nakedape.cc>, 25 April 2002.
#
# This script is copyright (C) 2002 by Wil Cooley and
# licensed under the GNU GPL <http://www.gnu.org//licenses/gpl.txt>
#
# Usage: migrate-pw-to-cyrus2.pl
#
# Purpose: Creates empty Cyrus mailboxes.
#
# Input: None.
#
# Notes: Set the default quota below. I used a default
# of 100MB more as a failsafe than a restriction.
#
# $Id: migrate-pw-to-cyrus2.pl,v 1.1 2002/04/26 00:56:09 wcooley Exp $
###
my $adminuser = "cyradmin" ;
my $server = "localhost" ;
my $quota = 100*1024 ; # 100MB
my $user_uid_start = 500 ;
my $err = 0 ;
my ($user,$p,$uid) ;

use Cyrus::IMAP::Admin;

$imapcon = Cyrus::IMAP::Admin->new($server) || die "Unable to connect to $server";

unless ($imapcon) {
die "Error creating IMAP connection object\n" ;
}

$imapcon->authenticate(-user => $adminuser, -mechanism => "LOGIN") ;

if ($imapcon->error) {
die $imapcon->error ;
}

print "\n" ;

setpwent() ;

while (($user,$p,$uid) = getpwent) {
if ($uid >= $user_uid_start) {
unless ($imapcon->list("user.$user")) {
$imapcon->create("user.$user") ;
if ($imapcon->error) {
print "ERROR: ", $imapcon->error, "\n" ;
next;
} ;
$imapcon->setquota("user.$user", "STORAGE", $quota) ;
if ($imapcon->error) {
print "ERROR: ", $imapcon->error, "\n";
next;
} ;
print "Created mailbox user.$user [$uid]\n" ;
}
}
}
endpwent() ;

Перенос содержимого почтовых ящиков с помощью formail и cyrus deliver

# Script to import mbox-format mailboxes to Cyrus folders
# Requires formail (from procmail)
#
# Note: As this runs cyrdeliver directly, you'll need to be
# a member of the mail group for it to work.
#
# Use this script at your own risk! I'm not responsible if
# it trashes your mail system :)
#
# By Michael-John Turner <mj@debian.org>
#

USER=$1
MAILBOX=$2
CYRUSFOLDER=$3
#CYRDELIVER=/usr/sbin/cyrdeliver
CYRDELIVER=/usr/lib/cyrus-imapd/deliver
FORMAIL=/usr/bin/formail

if ! [ -x "$FORMAIL" ]; then
echo ""
echo "formail (from procmail) is required to run this script"
echo ""
exit 1
fi

if [ "$USER" = "" ]; then
echo ""
echo "syntax: $0 user [mbox] [cyrus folder]"
echo ""
echo "If no mbox is specified, the user and mbox name are taken to be the same"
echo "If no cyrus folder is specified, the INBOX is used"
echo ""
exit 2
fi

if [ "$MAILBOX" == "" ]; then
MAILBOX=$USER
fi

if [ "$CYRUSFOLDER" == "" ]; then
echo "Adding mailbox '$MAILBOX' to Cyrus INBOX of user '$USER'..."
$FORMAIL -I "From " -s $CYRDELIVER $USER < $MAILBOX
else
echo "Adding mailbox '$MAILBOX' to Cyrus folder '$CYRUSFOLDER' of user '$USER'..."
$FORMAIL -I "From " -s $CYRDELIVER -m $CYRUSFOLDER $USER < $MAILBOX
fi

Перенос паролей

При миграции возникает желание убрать записи почтовых пользователей из /etc/passwd и перейти на хранение паролей в MySQL, LDAP или где нибудь еще. Прямого пути нет!

В качестве обходного пути можно попытаться использовать PAM-modules Сергея Позднякова http://puszcza.gnu.org.ua/software/pam-modules/

Устанавливаем pam_fshadow из указанного пакета. Копируем записи почтовых пользователей из файла /etc/shadow (/etc/master.passwd во FreeBSD) в новое место, например в /etc/mail/shadow. Пишем настройки PAM для сервисов pop, imap и, возможно, sieve.

auth sufficient pam_fshadow.so sysconfdir=/etc/mail nopass
account sufficient pam_fshadow.so sysconfdir=/etc/mail nopass

Дополнительно настраиваем SASL для проверки в MySQL. Вариант с pam_mysql менее интересен, т.к. не поддерживает виртуальные домены.

auth sufficient pam_fshadow.so sysconfdir=/etc/mail nopass
auth sufficient pam_mysql.so config_file=/etc/pam_mysql.conf
auth sufficient pam_fshadow.so sysconfdir=/etc/mail nopass
account sufficient pam_mysql.so config_file=/etc/pam_mysql.conf

Пример /etc/pam_mysql.conf
users.host=localhost;
users.database=maildb;
users.db_user=mailadmin;
users.db_passwd=mailpassword;
users.table=accountuser;
users.user_column=username;
users.password_column=password;
users.password_crypt=plain;
users.disconnect_every_operation=true;
verbose=0;
log.enabled=1;
log.table=logins;
log.message_column=message;
log.pid_column=pid;
log.user_column=username;
log.host_column=machineip;
log.time_column=logintime;