mail - SMTP con CRAM-MD5 en Java
mail smtp port java (7)
Probablemente esto no te ayude, pero CRAM-MD5 y CRAM-SHA1 son bastante fáciles de implementar, suponiendo que tienes la biblioteca correcta (md5 / sha1) y, idealmente, una biblioteca de codificación base64 (aunque las cosas de base64 son bastante fáciles de implementar tú mismo en un apuro).
La transacción se ve así:
C: AUTH CRAM-MD5
S: 334 BASE64(NONCE)
C: BASE64(USERNAME, " ", MD5((SECRET XOR opad),MD5((SECRET XOR ipad), NONCE)))
S: 235 Authentication succeeded
Donde NONCE es la cadena de desafío una vez, USERNAME es el nombre de usuario que está intentando autenticar, SECRET es el secreto compartido ("contraseña"), opad es 0x5C, y ipad es 0x36.
(CRAM-SHA1 sería la misma transacción, pero usando SHA1 () en lugar de MD5 () para hacer la digestión)
Entonces, aquí hay un ejemplo de una transacción CRAM-MD5 real
C: AUTH CRAM-MD5
S: 334 PDQ1MDMuMTIyMzU1Nzg2MkBtYWlsMDEuZXhhbXBsZS5jb20+
C: dXNlckBleGFtcGxlLmNvbSA4YjdjODA5YzQ0NTNjZTVhYTA5N2VhNWM4OTlmNGY4Nw==
S: 235 Authentication succeeded
Copia de seguridad del proceso un paso que obtiene:
S: 334 BASE64("<[email protected]>")
C: BASE64("[email protected] 8b7c809c4453ce5aa097ea5c899f4f87")
Al hacer una copia de seguridad un paso más antes de calcular el resumen, obtienes:
S: 334 BASE64("<[email protected]>")
C: BASE64("[email protected] ", MD5(("password" XOR opad),MD5(("password" XOR ipad), "<[email protected]>")))
Supongo que es un poco confuso ahora que lo escribo, pero créanme, en comparación con tratar de hacer NTLM / SPA a mano, es muy fácil. Si está motivado, en realidad es bastante fácil de implementar. O tal vez acabo de pasar mucho tiempo con las manos en las entrañas de los clientes de correo y servidores para pensarlo claramente nunca más ...
Necesito enviar correos electrónicos a través de un servidor SMTP (externo) desde Java; sin embargo, este servidor solo aceptará la autenticación CRAM-MD5, que no es compatible con JavaMail.
¿Cuál sería una buena forma de enviar estos correos electrónicos? (Debe estar en Java)
Sin embargo, esto no le ayuda directamente, las conexiones IMAP en JavaMail son compatibles con SASL (y, por lo tanto, CRAM-MD5, consulte la documentación de Java SASL ) si establece la propiedad booleano mail.imap.sasl.enable
en true
.
Desafortunadamente, no hay mail.smtp.sasl.enable
propiedad mail.smtp.sasl.enable
y SASL no se puede habilitar para SMTP en JavaMail. :-(
Sin embargo, puede descargar el código fuente de JavaMail y puede intentar editar el código SMTP para que sea compatible con SASL de manera similar al código IMAP. ¡Buena suerte!
Probé el código en el ejemplo de una transacción CRAM-MD5 real, y también en el ejemplo dado en el RFC 2195.
No funciona porque la conversión a una cadena hexadecimal no es correcta. Por ejemplo, con este código, obtendrá "b913a62c7eda7a495b4e6e7334d3890" en lugar de "b913a602c7eda7a495b4e6e7334d3890" y la cadena de autenticación enviada no será correcta.
Si descarga el código fuente de javaMail, verá la implementación de la función aHex en la unidad "DigestMD5". Al usar esta conversión, funcionará.
Programa CRAMMD5 muy simple en JAVA
import java.security.*;
class CRAMMD5Test
{
public static void main(String[] args) throws Exception
{
// This represents the BASE64 encoded timestamp sent by the POP server
String dataString = Base64Decoder.decode("PDAwMDAuMDAwMDAwMDAwMEBteDEuc2VydmVyLmNvbT4=");
byte[] data = dataString.getBytes();
// The password to access the account
byte[] key = new String("password").getBytes();
// The address of the e-mail account
String user = "[email protected]";
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.reset();
if (key.length > 64)
key = md5.digest(key);
byte[] k_ipad = new byte[64];
byte[] k_opad = new byte[64];
System.arraycopy(key, 0, k_ipad, 0, key.length);
System.arraycopy(key, 0, k_opad, 0, key.length);
for (int i=0; i<64; i++)
{
k_ipad[i] ^= 0x36;
k_opad[i] ^= 0x5c;
}
byte[] i_temp = new byte[k_ipad.length + data.length];
System.arraycopy(k_ipad, 0, i_temp, 0, k_ipad.length);
System.arraycopy(data, 0, i_temp, k_ipad.length, data.length);
i_temp = md5.digest(i_temp);
byte[] o_temp = new byte[k_opad.length + i_temp.length];
System.arraycopy(k_opad, 0, o_temp, 0, k_opad.length);
System.arraycopy(i_temp, 0, o_temp, k_opad.length, i_temp.length);
byte[] result = md5.digest(o_temp);
StringBuffer hexString = new StringBuffer();
for (int i=0;i < result.length; i++) {
hexString.append(Integer.toHexString((result[i] >>> 4) & 0x0F));
hexString.append(Integer.toHexString(0x0F & result[i]));
}
System.out.println(Base64Encoder.encode(user + " " + hexString.toString()));
}
}
Cambio:
for (int i=0; i<result.length; i++)
hexString.append(Integer.toHexString(0xFF & result[i]));
A:
for (int i=0;i < result.length; i++) {
hexString.append(Integer.toHexString((result[i] >>> 4) & 0x0F));
hexString.append(Integer.toHexString(0x0F & result[i]));
}
Aquí hay un hilo que dice que necesitas agregar la siguiente propiedad:
props.put("mail.smtp.auth.mechanisms", "CRAM-MD5")
También en la implementación Geronimo hay CramMD5Authenticator
Espero que ayude a resolver esta vieja pregunta.
Desde Java Mail 1.4.4, se admite CRAM-MD5 para usar con smtp. Simplemente configure este parámetro para sus propiedades y funcionará:
props.put("mail.smtp.sasl.enable", "true");