我正在尝试使用UTL_MAIL.Send打包过程从PL / SQL程序发送电子邮件。但我收到以下错误:
ORA-29278:SMTP瞬态错误:421服务不可用
我在网上搜索,发现发生此错误是因为运行我的Oracle数据库的主机上没有SMTP服务。
现在,如果我想使用其他SMTP服务器,例如hotmail的“smtp.live.com”,我需要我的用户名和密码。
如何将我的密码输入UTL_MAIL.Send
程序调用?
(根据我的理解,为了使用任何其他SMTP服务器,我必须提供我的用户名/密码)。我知道要使用UTL_MAIL
包,我们使用初始化参数设置SMTP服务器,我们可以在“Sender”参数中给出用户名,但问题是我们应该在哪里提供密码?
答案 0 :(得分:2)
基本上你必须使用"较低级别" UTL_SMTP
包,以便发送远程SMTP服务器所需的各种SMTP邮件。
-- prepare base64 encoded username and password
l_encoded_username := UTL_RAW.cast_to_varchar2(UTL_ENCODE.base64_encode(UTL_RAW.cast_to_raw(username)));
l_encoded_password := UTL_RAW.cast_to_varchar2(UTL_ENCODE.base64_encode(UTL_RAW.cast_to_raw(password)));
-- Open connection and send EHLO and AUTH messages
l_conn := UTL_SMTP.open_connection(smtpHost, smtpPort);
UTL_SMTP.ehlo(l_conn, smtpHost);--DO NOT USE HELO
UTL_SMTP.command(l_conn, 'AUTH', 'LOGIN');
UTL_SMTP.command(l_conn, l_encoded_username);
UTL_SMTP.command(l_conn, l_encoded_password);
这里的主要问题是您需要能够使用"权利"发送AUTH
消息。服务器的身份验证方案。我不能特别对" smtp.live.com" 说,但根据服务器的配置,它们可能是不同的身份验证方案,例如{{1 }}和PLAIN
,LOGIN
,...通常(总是?)参数(DIGEST_MD5
,username
)是base64编码的。
但坏消息,因为您现在使用的是低级库,您必须自己实现SMTP protocol的客户端部分。来自上面的相同来源(由我自己编辑,只保留绝对最少的必要内容):
password
现在,对于非常坏消息:某些服务器需要安全连接。声称像UTL_SMTP.mail(l_conn, mailFrom);
UTL_SMTP.rcpt(l_conn, rcptTo);
[...]
--start multi line message
UTL_SMTP.open_data(l_conn);
--prepare mail header
UTL_SMTP.write_data(l_conn, 'To: ' || rcptTo || crlf);
UTL_SMTP.write_data(l_conn, 'From: ' || mailFrom || crlf);
UTL_SMTP.write_data(l_conn, 'Subject: ' || messageSubject || crlf);
--include the message body
UTL_SMTP.write_data(l_conn, messageBody || crlf || crlf);
--send the email and close connection
UTL_SMTP.close_data(l_conn);
UTL_SMTP.quit(l_conn);
这样的东西。遗憾的是,仅从Oracle Database 11g第2版(11.2.0.2)开始支持UTL_SMTP.STARTTLS
。
如果您很幸运能够使用最新版本的Oracle,那么您应该编写类似的内容来打开与服务器的安全连接:
530 Must issue a STARTTLS command first
引用Oracle的文档:
SSL / TLS需要一个Oracle钱包,必须在OPEN_CONNECTION函数打开连接时指定。
请参阅相应的文档以查看how to create and manage wallet
几点读数:
l_conn := UTL_SMTP.open_connection(l_conn, smtpHost,
wallet_path => 'file:/oracle/wallets/smtp_wallet',
wallet_password => 'password',
secure_connection_before_smtp => FALSE);
UTL_SMTP.starttls(l_conn);
正确发送邮件。答案 1 :(得分:0)
在网上找到了这个。看起来这些中的任何一个应该可以解决问题:
AUTH PLAIN
v_plain_string :=
UTL_RAW.cast_to_varchar2(
UTL_ENCODE.base64_encode(UTL_RAW.cast_to_raw('my_user_name'||chr(0)||'my_user_name'||chr(0)||'my_secret_password'))
);
v_connection := UTL_SMTP.open_connection(:v_smtp_server);
UTL_SMTP.ehlo(v_connection, 'mydomain.com'); -- Must use EHLO vs HELO
UTL_SMTP.command(v_connection, 'AUTH', 'PLAIN ' || v_plain_string);
AUTH LOGIN
v_username_b64 :=
UTL_RAW.cast_to_varchar2(
UTL_ENCODE.base64_encode(UTL_RAW.cast_to_raw(:v_username))
);
v_password_b64 :=
UTL_RAW.cast_to_varchar2(
UTL_ENCODE.base64_encode(UTL_RAW.cast_to_raw(:v_password))
);
v_connection := UTL_SMTP.open_connection(:v_smtp_server);
UTL_SMTP.ehlo(v_connection, 'mydomain.com'); -- Must use EHLO vs HELO
UTL_SMTP.command(v_connection, 'AUTH', 'LOGIN'); -- should receive a 334 response, prompting for username
UTL_SMTP.command(v_connection, v_username_b64); -- should receive a 334 response, prompting for password
UTL_SMTP.command(v_connection, v_password_b64); -- should receive a 235 response, you are authenticated
我想当你谈到“发件人”参数时,你可能会引用电子邮件本身的“发件人”标题。