Correo electrónico · 14 min read · Jan 09, 2026
Usuarios Virtuales Y Dominios Con Postfix, Courier, MySQL Y SquirrelMail (CentOS 6.0 x86_64) - Página 6
18 Instalando SquirrelMail
SquirrelMail es una interfaz de webmail que permitirá a tus usuarios enviar y recibir correos electrónicos en un navegador. Este capítulo muestra cómo instalarlo y ajustarlo a nuestra configuración para que los usuarios incluso puedan cambiar la contraseña de su cuenta de correo desde la interfaz de SquirrelMail.
Para instalar SquirrelMail, ejecutamos:
yum install squirrelmail php-pear-DBDespués reiniciamos Apache:
/etc/init.d/httpd restartSquirrelMail viene con algunos plugins preinstalados, desafortunadamente ninguno de ellos es capaz de permitirnos cambiar nuestra contraseña de correo en nuestra base de datos MySQL. Pero existe el plugin Change SQL Password que podemos instalar manualmente:
cd /usr/share/squirrelmail/plugins
wget http://www.squirrelmail.org/plugins/change_sqlpass-3.3-1.2.tar.gz
tar xvfz change_sqlpass-3.3-1.2.tar.gz
cd change_sqlpass
cp config.php.sample config.phpAhora debemos editar config.php y ajustarlo a nuestra configuración. Por favor ajusta las variables $csp_dsn, $lookup_password_query, $password_update_queries, $password_encryption, $csp_salt_static y $csp_delimiter de la siguiente manera y comenta $csp_salt_query:
vi config.php| [...] $csp_dsn = 'mysql://mail_admin:mail_admin_password@localhost/mail'; [...] $lookup_password_query = 'SELECT count(*) FROM users WHERE email = "%1" AND password = %4'; [...] $password_update_queries = array('UPDATE users SET password = %4 WHERE email = "%1"'); [...] $password_encryption = 'MYSQLENCRYPT'; [...] $csp_salt_static = 'LEFT(password, 2)'; [...] //$csp_salt_query = 'SELECT salt FROM users WHERE username = "%1"'; [...] $csp_delimiter = '@'; [...] |
El archivo completo se ve de la siguiente manera:
| * 2002-2005 Paul Lesneiwski <[email protected]> * Este programa está licenciado bajo GPL. Consulta COPYING para más detalles * * @package plugins * @subpackage Change SQL Password * */ // Variables Globales, no toques estas a menos que quieras romper el plugin // global $csp_dsn, $password_update_queries, $lookup_password_query, $force_change_password_check_query, $password_encryption, $csp_salt_query, $csp_salt_static, $csp_secure_port, $csp_non_standard_http_port, $csp_delimiter, $csp_debug, $min_password_length, $max_password_length, $include_digit_in_password, $include_uppercase_letter_in_password, $include_lowercase_letter_in_password, $include_nonalphanumeric_in_password; // csp_dsn // // Teóricamente, cualquier base de datos SQL soportada por Pear debería ser soportada // aquí. El DSN (nombre de fuente de datos) debe contener la información necesaria // para conectarse a tu backend de base de datos. Un ejemplo de MySQL se incluye a continuación. // Para más detalles sobre la sintaxis del DSN y la lista de tipos de bases de datos soportadas, // consulta: // http://pear.php.net/manual/en/package.database.db.intro-dsn.php // //$csp_dsn = 'mysql://user:password@localhost/email_users'; $csp_dsn = 'mysql://mail_admin:mail_admin_password@localhost/mail'; // lookup_password_query // // Este plugin siempre verificará la antigua contraseña del usuario // contra su contraseña de inicio de sesión, pero también se puede // hacer una verificación adicional contra la base de datos para más seguridad si // así lo deseas. Si no necesitas la verificación de contraseña adicional, // asegúrate de que esta configuración esté vacía. // // Esta es una consulta que devuelve un valor positivo si un usuario // y un par de contraseñas se encuentran en la base de datos. // // Esta consulta debería devolver un valor (una fila, una columna), el // valor siendo idealmente un uno o un cero, simplemente indicando que // el par usuario/contraseña efectivamente existe en la base de datos. // // %1 en esta consulta será reemplazado con el nombre de usuario completo // (incluyendo dominio), como "[email protected]" // %2 en esta consulta será reemplazado con el nombre de usuario (sin // ninguna parte del dominio), como "jose" // %3 en esta consulta será reemplazado con el nombre de dominio, // como "example.com" // %4 en esta consulta será reemplazado con la actual (antigua) // contraseña en cualquier formato de cifrado que sea necesario según otras // configuraciones del plugin (Ten en cuenta que la sintaxis de // la contraseña será proporcionada dependiendo de tus elecciones de cifrado, // así que NUNCA necesitas proporcionar comillas alrededor de este // valor en la consulta aquí.) // %5 en esta consulta será reemplazado con la actual (antigua) // contraseña en texto plano sin cifrar. Si no usas ningún // cifrado de contraseña, %4 y %5 serán los mismos valores, // excepto que %4 tendrá comillas dobles alrededor y %5 no. // //$lookup_password_query = ''; // SEGURIDAD TERRIBLE: $lookup_password_query = 'SELECT count(*) FROM users WHERE username = "%1" AND plain_password = "%5"'; //$lookup_password_query = 'SELECT count(*) FROM users WHERE username = "%1" AND crypt_password = %4'; $lookup_password_query = 'SELECT count(*) FROM users WHERE email = "%1" AND password = %4'; // password_update_queries // // Un array de consultas SQL que se ejecutarán // cada vez que se intente cambiar la contraseña. // // Cualquier número de consultas puede ser incluido aquí. // Las consultas se ejecutarán en el orden dado aquí. // // %1 en todas las consultas será reemplazado con el nombre de usuario completo // (incluyendo dominio), como "[email protected]" // %2 en todas las consultas será reemplazado con el nombre de usuario (sin // ninguna parte del dominio), como "jose" // %3 en todas las consultas será reemplazado con el nombre de dominio, // como "example.com" // %4 en todas las consultas será reemplazado con la nueva contraseña // en cualquier formato de cifrado que sea necesario según otras // configuraciones del plugin (Ten en cuenta que la sintaxis de // la contraseña será proporcionada dependiendo de tus // elecciones de cifrado, así que NUNCA necesitas proporcionar comillas // alrededor de este valor en las consultas aquí.) // %5 en todas las consultas será reemplazado con la nueva contraseña // en texto plano sin cifrar - ¡CUIDADO! Si no usas // ningún cifrado de contraseña, %4 y %5 serán los mismos // valores, excepto que %4 tendrá comillas dobles alrededor // y %5 no. // // $password_update_queries = array( // 'UPDATE users SET crypt_password = %4 WHERE username = "%1"', // 'UPDATE user_flags SET force_change_pwd = 0 WHERE username = "%1"', // 'UPDATE users SET crypt_password = %4, force_change_pwd = 0 WHERE username = "%1"', // ); $password_update_queries = array('UPDATE users SET password = %4 WHERE email = "%1"'); // force_change_password_check_query // // Una consulta que verifica si hay una bandera que indica si un usuario // debe ser obligado a cambiar su contraseña. Esta consulta // debería devolver un valor (una fila, una columna) que es // cero si el usuario NO necesita cambiar su contraseña, // o uno si el usuario debe ser obligado a cambiarla ahora. // // Esta configuración debería ser una cadena vacía si no deseas // habilitar esta funcionalidad. // // %1 en esta consulta será reemplazado con el nombre de usuario completo // (incluyendo dominio), como "[email protected]" // %2 en esta consulta será reemplazado con el nombre de usuario (sin // ninguna parte del dominio), como "jose" // %3 en esta consulta será reemplazado con el nombre de dominio, // como "example.com" // //$force_change_password_check_query = 'SELECT IF(force_change_pwd = "yes", 1, 0) FROM users WHERE username = "%1"'; //$force_change_password_check_query = 'SELECT force_change_pwd FROM users WHERE username = "%1"'; $force_change_password_check_query = ''; // password_encryption // // ¿Qué método de cifrado usas para almacenar contraseñas // en tu base de datos? Por favor usa uno de los siguientes, // exactamente como lo ves: // // NONE Las contraseñas se almacenan como texto plano solamente // MYSQLPWD Las contraseñas se almacenan usando la función password() de MySQL // MYSQLENCRYPT Las contraseñas se almacenan usando la función encrypt() de MySQL // PHPCRYPT Las contraseñas se almacenan usando la función crypt() de PHP // MD5CRYPT Las contraseñas se almacenan usando el algoritmo MD5 cifrado // MD5 Las contraseñas se almacenan como hash MD5 // //$password_encryption = 'MYSQLPWD'; $password_encryption = 'MYSQLENCRYPT'; // csp_salt_query // csp_salt_static // // Los tipos de cifrado que necesitan una sal necesitan saber dónde obtener // esa sal. Si tienes un valor de sal constante y conocido, debes // definirlo en $csp_salt_static. De lo contrario, deja ese // valor vacío y define un valor para $csp_salt_query. // // Deja ambos valores vacíos si no necesitas (o usas) sales // para cifrar tus contraseñas. // // La consulta debería devolver un valor (una fila, una columna) que // es el valor de sal para la contraseña del usuario actual. Esta // consulta es ignorada si $csp_salt_static es cualquier cosa menos vacía. // // %1 en esta consulta será reemplazado con el nombre de usuario completo // (incluyendo dominio), como "[email protected]" // %2 en esta consulta será reemplazado con el nombre de usuario (sin // ninguna parte del dominio), como "jose" // %3 en esta consulta será reemplazado con el nombre de dominio, // como "example.com" // //$csp_salt_static = 'LEFT(crypt_password, 2)'; //$csp_salt_static = '"a4"'; // usa este formato con MYSQLENCRYPT //$csp_salt_static = '$2$blowsomefish$'; // usa este formato con PHPCRYPT //$csp_salt_static = ''; $csp_salt_static = 'LEFT(password, 2)'; //$csp_salt_query = 'SELECT SUBSTRING_INDEX(crypt_password, '$', 1) FROM users WHERE username = "%1"'; //$csp_salt_query = 'SELECT SUBSTRING(crypt_password, (LENGTH(SUBSTRING_INDEX(crypt_password, '$', 2)) + 2)) FROM users WHERE username = "%1"'; //$csp_salt_query = 'SELECT salt FROM users WHERE username = "%1"'; //$csp_salt_query = ''; // csp_secure_port // // Puedes asegurarte de que se use cifrado SSL durante el cambio de contraseña // configurando esto al puerto en el que se sirve tu HTTPS // (443 es típico). Configura a cero si no deseas forzar // una conexión HTTPS cuando los usuarios cambian sus contraseñas. // // Puedes anular este valor para ciertos dominios, usuarios o // niveles de servicio a través del plugin de Inicio de Sesión de Host Virtual (vlogin) // configurando un valor para $vlogin_csp_secure_port en la configuración de vlogin. // $csp_secure_port = 0; //$csp_secure_port = 443; // csp_non_standard_http_port // // Si sirves solicitudes web HTTP estándar en un puerto no estándar // (cualquier cosa que no sea el puerto 80), debes especificar ese // número de puerto aquí. Configura a cero de lo contrario. // // Puedes anular este valor para ciertos dominios, usuarios o // niveles de servicio a través del plugin de Inicio de Sesión de Host Virtual (vlogin) // configurando un valor para $vlogin_csp_non_standard_http_port // en la configuración de vlogin. // //$csp_non_standard_http_port = 8080; $csp_non_standard_http_port = 0; // min_password_length // max_password_length // include_digit_in_password // include_uppercase_letter_in_password // include_lowercase_letter_in_password // include_nonalphanumeric_in_password // // Puedes establecer las longitudes mínimas y máximas de contraseña que // aceptas o dejar esas configuraciones en cero para indicar que // no se debe aplicar ningún límite. // // Activa cualquiera de las otras configuraciones aquí para verificar que la // nueva contraseña contenga al menos un dígito, letra mayúscula, // letra minúscula y/o un carácter no alfanumérico. // $min_password_length = 6; $max_password_length = 0; $include_digit_in_password = 0; $include_uppercase_letter_in_password = 0; $include_lowercase_letter_in_password = 0; $include_nonalphanumeric_in_password = 0; // csp_delimiter // // si tu sistema tiene nombres de usuario con algo diferente a // un signo "@" separando la parte del usuario y del dominio, // especifica ese carácter aquí // //$csp_delimiter = '|'; $csp_delimiter = '@'; // modo de depuración // $csp_debug = 0; ?> |
El plugin Change SQL Password también depende del plugin Compatibility que instalamos de la siguiente manera:
cd /usr/share/squirrelmail/plugins
wget http://www.squirrelmail.org/countdl.php?fileurl=http%3A%2F%2Fwww.squirrelmail.org%2Fplugins%2Fcompatibility-2.0.16-1.0.tar.gz
tar xvfz compatibility-2.0.16-1.0.tar.gzAhora debemos ir a la configuración de SquirrelMail y decirle a SquirrelMail que usamos Courier como nuestro servidor POP3 e IMAP y habilitar los plugins Change SQL Password y Compatibility:
/usr/share/squirrelmail/config/conf.plVerás el siguiente menú. Navega a través de él como se indica:
Configuración de SquirrelMail : Leer: config.php (1.4.0)
---------------------------------------------------------
Menú Principal --
1. Preferencias de Organización
2. Configuraciones del Servidor
3. Valores Predeterminados de Carpetas
4. Opciones Generales
5. Temas
6. Libros de Direcciones
7. Mensaje del Día (MOTD)
8. Plugins
9. Base de Datos
10. Idiomas
D. Establecer configuraciones predefinidas para servidores IMAP específicos
C Apagar color
S Guardar datos
Q Salir
Comando >> <-- D
Configuración de SquirrelMail : Leer: config.php
---------------------------------------------------------
Mientras hemos estado construyendo SquirrelMail, hemos descubierto algunas
preferencias que funcionan mejor con algunos servidores que no
funcionan tan bien con otros. Si seleccionas tu servidor IMAP, esta
opción establecerá algunas configuraciones predefinidas para
ese servidor.
Por favor nota que aún necesitarás revisar y asegurarte de que
todo esté correcto. Esto no cambia todo. Solo hay
algunas configuraciones que esto cambiará.
Por favor selecciona tu servidor IMAP:
bincimap = Servidor IMAP Binc
courier = Servidor IMAP Courier
cyrus = Servidor IMAP Cyrus
dovecot = Servidor IMAP Seguro Dovecot
exchange = Servidor IMAP Microsoft Exchange
hmailserver = hMailServer
macosx = Servidor de Correo Mac OS X
mercury32 = Mercury/32
uw = Servidor IMAP de la Universidad de Washington
gmail = Acceso IMAP a cuentas de correo de Google (Gmail)
salir = No cambiar nada
Comando >> <-- courier
imap_server_type = courier
default_folder_prefix = INBOX.
trash_folder = Trash
sent_folder = Sent
draft_folder = Drafts
show_prefix_option = false
default_sub_of_inbox = false
show_contain_subfolders_option = false
optional_delimiter = .
delete_folder = true
Presiona cualquier tecla para continuar... <-- presiona alguna tecla
Configuración de SquirrelMail : Leer: config.php (1.4.0)
---------------------------------------------------------
Menú Principal --
1. Preferencias de Organización
2. Configuraciones del Servidor
3. Valores Predeterminados de Carpetas
4. Opciones Generales
5. Temas
6. Libros de Direcciones
7. Mensaje del Día (MOTD)
8. Plugins
9. Base de Datos
10. Idiomas
D. Establecer configuraciones predefinidas para servidores IMAP específicos
C Apagar color
S Guardar datos
Q Salir
Comando >> <-- 8
Configuración de SquirrelMail : Leer: config.php (1.4.0)
---------------------------------------------------------
Plugins
Plugins Instalados
1. delete_move_next
2. squirrelspell
3. newmail
Plugins Disponibles:
4. administrator
5. bug_report
6. calendar
7. change_sqlpass
8. compatibility
9. filters
10. fortune
11. info
12. listcommands
13. mail_fetch
14. message_details
15. sent_subfolders
16. spamcop
17. test
18. translate
R Regresar al Menú Principal
C Apagar color
S Guardar datos
Q Salir
Comando >> <-- 8 (o cualquier número que tenga el plugin de compatibilidad - es necesario para el plugin change_sqlpass)
Configuración de SquirrelMail : Leer: config.php (1.4.0)
---------------------------------------------------------
Plugins
Plugins Instalados
1. delete_move_next
2. squirrelspell
3. newmail
4. compatibility
Plugins Disponibles:
5. administrator
6. bug_report
7. calendar
8. change_sqlpass
9. filters
10. fortune
11. info
12. listcommands
13. mail_fetch
14. message_details
15. sent_subfolders
16. spamcop
17. test
18. translate
R Regresar al Menú Principal
C Apagar color
S Guardar datos
Q Salir
Comando >> <-- 8 (el número del plugin change_sqlpass)
Configuración de SquirrelMail : Leer: config.php (1.4.0)
---------------------------------------------------------
Plugins
Plugins Instalados
1. delete_move_next
2. squirrelspell
3. newmail
4. compatibility
5. change_sqlpass
Plugins Disponibles:
6. administrator
7. bug_report
8. calendar
9. filters
10. fortune
11. info
12. listcommands
13. mail_fetch
14. message_details
15. sent_subfolders
16. spamcop
17. test
18. translate
R Regresar al Menú Principal
C Apagar color
S Guardar datos
Q Salir
Comando >> <-- S
Configuración de SquirrelMail : Leer: config.php (1.4.0)
---------------------------------------------------------
Plugins
Plugins Instalados
1. delete_move_next
2. squirrelspell
3. newmail
4. compatibility
5. change_sqlpass
Plugins Disponibles:
6. administrator
7. bug_report
8. calendar
9. filters
10. fortune
11. info
12. listcommands
13. mail_fetch
14. message_details
15. sent_subfolders
16. spamcop
17. test
18. translate
R Regresar al Menú Principal
C Apagar color
S Guardar datos
Q Salir
Comando >> <-- S
Datos guardados en config.php
Presiona enter para continuar... <-- ENTER
Configuración de SquirrelMail : Leer: config.php (1.4.0)
---------------------------------------------------------
Plugins
Plugins Instalados
1. delete_move_next
2. squirrelspell
3. newmail
4. compatibility
5. change_sqlpass
Plugins Disponibles:
6. administrator
7. bug_report
8. calendar
9. filters
10. fortune
11. info
12. listcommands
13. mail_fetch
14. message_details
15. sent_subfolders
16. spamcop
17. test
18. translate
R Regresar al Menú Principal
C Apagar color
S Guardar datos
Q Salir
Comando >> <-- QUna última cosa que necesitamos hacer es modificar el archivo /etc/squirrelmail/config_local.php y comentar la variable $default_folder_prefix - si no haces esto, verás el siguiente mensaje de error en SquirrelMail después de haber iniciado sesión: Query: CREATE “Sent” Reason Given: Invalid mailbox name.
vi /etc/squirrelmail/config_local.php| |
Ahora puedes escribir en http://server1.example.com/webmail o http://192.168.0.110/webmail en tu navegador para acceder a SquirrelMail.
Inicia sesión con tu dirección de correo electrónico (por ejemplo, [email protected]) y tu contraseña:

Deberías encontrar el correo electrónico de bienvenida en tu bandeja de entrada:


Para cambiar tu contraseña, ve a Opciones y luego selecciona Cambiar Contraseña:

Escribe tu contraseña actual y luego tu nueva contraseña dos veces:

Después de haber cambiado la contraseña, tendrás que iniciar sesión nuevamente con la nueva contraseña:

19 VMA (Interfaz de Administración de Correo Virtual)
Virtual Mail Admin (VMA) es una pequeña aplicación web basada en PHP escrita para gestionar el sistema de correo electrónico configurado en esta guía. No lo probé, pero pensé en compartirlo.
Esto es lo que el desarrollador (Charl Loubser) me escribió en un correo electrónico:
*”Hola,
No sé si te gustará esto, o si tiene algún uso para ti, pero pensé en compartirlo:
Escribí una pequeña aplicación web para la configuración que hiciste en el Howto: https://www.howtoforge.com/virtual-users-domains-postfix-courier-mysql-squirrelmail-ubuntu-10.04
Si lo apruebas y crees que vale la pena compartirlo en tu tutorial, eres más que bienvenido, y puedes sentirte libre de hacerlo.
Como se menciona en el readme, esta no es una aplicación perfecta, pero hace el trabajo por ahora, y creo que es relativamente segura en un entorno cerrado (configuración LAN entre servidores).
El archivo rar con la aplicación está adjunto, pero también se puede descargar en: http://code.google.com/p/vma/ “*
20 Referencias
Tutorial: Servicio de Correo Electrónico estilo ISP con Debian-Sarge y Postfix 2.1: http://workaround.org/articles/ispmail-sarge/
Postfix + Cuota: http://vhcs.net/new/modules/newbb/viewtopic.php?topic_id=3496&forum=17
Contraseñas de Correo Encriptadas usando saslauthd: http://www.syscp.de/docs/public/contrib/cryptedmailpws
21 Enlaces
- Postfix MTA: http://www.postfix.org/
- Parche de Cuota de Postfix: http://web.onda.com.br/nadal/
- phpMyAdmin: http://www.phpmyadmin.net/
- SquirrelMail: http://www.squirrelmail.org/
- CentOS: http://www.centos.org/
Recibe nuevas publicaciones en tu bandeja de entrada.
No spam. Cancela la suscripción en cualquier momento.