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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-19 02:32:55  来源:igfitidea点击:

Give credentials to UTL_MAIL.SEND to bypass ORA-29278

sqloracleemail

提问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.Sendprocedure 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_MAILpackage, 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_MAILpackage,我们用初始化参数设置SMTP服务器,我们可以在“Sender”参数中提供用户名,但问题是我们应该在哪里提供密码?

回答by Sylvain Leroux

Basically you have to use the "lower level" UTL_SMTPpackage in order to send the various SMTP messages required by the distant SMTP server.

基本上,您必须使用“低级”UTL_SMTP包才能发送远程 SMTP 服务器所需的各种 SMTP 消息。

Authentication

验证

From Stefano Ghio's blog:

来自Stefano Ghio 的博客

 -- 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 AUTHmessage 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 PLAINand LOGIN, DIGEST_MD5, ... Usually (always ?) the parameters (username, password) are base64 encoded.

这里的主要问题是您需要能够AUTH使用服务器的“正确”身份验证方案发送消息。我不能说“smtp.live.com”明确,但根据服务器的配置,它们可能是不同的身份验证方案,如PLAINLOGINDIGEST_MD5......通常(总是?)的参数(usernamepassword)的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.STARTTLSis 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:

更多读物:

回答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.

我还认为,当您谈论“发件人”参数时,您可能指的是电子邮件本身的“发件人”标头。