oracle 向 UTL_MAIL.SEND 提供凭据以绕过 ORA-29278
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26186179/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Give credentials to UTL_MAIL.SEND to bypass ORA-29278
提问by user2755525
I am trying to send email from a PL/SQL program using UTL_MAIL.Send packaged procedure. But I am getting the following error:
我正在尝试使用 UTL_MAIL.Send 打包过程从 PL/SQL 程序发送电子邮件。但我收到以下错误:
ORA-29278: SMTP transient error: 421 Service not available
ORA-29278: SMTP 瞬时错误: 421 服务不可用
I searched on web, and found that this error occurs because there is no SMTP service on the host running my Oracle database.
我在网上查了一下,发现这个错误是因为运行我的Oracle数据库的主机上没有SMTP服务。
Now if I want to use another SMTP server, for example , hotmail's "smtp.live.com", i need my user name and password.
现在如果我想使用另一个 SMTP 服务器,例如,hotmail 的“smtp.live.com”,我需要我的用户名和密码。
How can I give my password into the UTL_MAIL.Send
procedure call?
我怎样才能在UTL_MAIL.Send
过程调用中提供我的密码?
(according to my understanding, in order to use any other SMTP server, I have to provide my username/password). I know that to use UTL_MAIL
package, we set the SMTP server with an initialization parameter, and we can give username in "Sender" parameter, but the question is where should we give the password?
(根据我的理解,为了使用任何其他 SMTP 服务器,我必须提供我的用户名/密码)。我知道要使用UTL_MAIL
package,我们用初始化参数设置SMTP服务器,我们可以在“Sender”参数中提供用户名,但问题是我们应该在哪里提供密码?
回答by Sylvain Leroux
Basically you have to use the "lower level" UTL_SMTP
package in order to send the various SMTP messages required by the distant SMTP server.
基本上,您必须使用“低级”UTL_SMTP
包才能发送远程 SMTP 服务器所需的各种 SMTP 消息。
Authentication
验证
From Stefano Ghio's blog:
-- 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);
The main issue here is that you need be able to send the AUTH
message using the "right" authentication scheme for your server. I can't say for "smtp.live.com"specifically, but depending the server's configuration, they might be different authentication scheme, like PLAIN
and LOGIN
, DIGEST_MD5
, ... Usually (always ?) the parameters (username
, password
) are base64 encoded.
这里的主要问题是您需要能够AUTH
使用服务器的“正确”身份验证方案发送消息。我不能说“smtp.live.com”明确,但根据服务器的配置,它们可能是不同的身份验证方案,如PLAIN
和LOGIN
,DIGEST_MD5
......通常(总是?)的参数(username
,password
)的base64编码。
Sending mail
发送邮件
But the bad newsis, since you are now using a low-level library, you have to implement the client part of the SMTP protocolyourself. From the same source as above (edited by myself to only keep the absolutely minimum necessary stuff):
但坏消息是,由于您现在使用的是低级库,您必须自己实现SMTP 协议的客户端部分。来自与上述相同的来源(由我自己编辑以只保留绝对最少的必要内容):
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);
Using SSL/TLS
使用 SSL/TLS
And now, for the very bad news: some server required a secure connection. Claiming something like 530 Must issue a STARTTLS command first
. Unfortunately, UTL_SMTP.STARTTLS
is only supported starting from Oracle Database 11g release 2 (11.2.0.2).
现在,非常坏的消息是:某些服务器需要安全连接。声称之类的东西530 Must issue a STARTTLS command first
。遗憾的是,UTL_SMTP.STARTTLS
仅从 Oracle Database 11g 第 2 版 (11.2.0.2) 开始支持。
If you are lucky enougth to use a recent version of Oracle, you should write something like that to open a secure connection with your server:
如果您足够幸运使用最新版本的 Oracle,您应该编写类似的内容来打开与您的服务器的安全连接:
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);
To quote Oracle's documentation:
引用 Oracle 的文档:
SSL/TLS requires an Oracle wallet which must be specified when the connection was opened by the OPEN_CONNECTION Functions.
SSL/TLS 需要一个 Oracle 钱包,必须在 OPEN_CONNECTION 函数打开连接时指定该钱包。
Please see the corresponding documentation to see how to create and manage wallet
请查看相应文档了解如何创建和管理钱包
Few more readings:
更多读物:
- Oracle's documentation about sending e-mail from PL/SQL has some nice examples too depicting you to properly send your mail message using
UTL_SMTP
. - See the SMTP Authentification Wikipedia pagefor a transcription of a typical SMTP session.
- Oracle 的关于从 PL/SQL 发送电子邮件的文档也有一些很好的例子,描述了如何使用
UTL_SMTP
. - 有关典型 SMTP 会话的转录,请参阅SMTP 身份验证维基百科页面。
回答by myte
found this online. seems like either of these should do the trick:
在网上找到了这个。似乎其中任何一个都可以解决问题:
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
also i think when you talk about the "Sender" parameter you might be referring to the "From" header for the email itself.
我还认为,当您谈论“发件人”参数时,您可能指的是电子邮件本身的“发件人”标头。