I'm sending thousands of emails via Oracle 18c to an SMTP server. The emails are different.
I'm using the following code in a loop that I put inside a job. This code works great, however the execution time is quite slow.
Is there any way to speed it up? For example, opening the SMTP connection only once and use it for the entire loop.
declare
Connexion UTL_SMTP.connection;
l_boundary VARCHAR2(50) := '----=*#abc1234321cba#*=';
-- other variables are declared somewhere else...
Begin
Connexion := UTL_SMTP.open_connection(Host, Port);
UTL_SMTP.AUTH(Connexion,KeyName,KeyValue, 'PLAIN');
UTL_SMTP.helo(Connexion, Host);
UTL_SMTP.mail(Connexion, MailFrom_);
-- Add email
UTL_SMTP.rcpt(Connexion, EmailAddress);
-- Open reader to write data
UTL_SMTP.open_data(Connexion);
-- Date
UTL_SMTP.write_data(Connexion, 'Date: ' || TO_CHAR(SYSDATE, 'DD-MON-YYYY HH24:MI:SS') || UTL_TCP.crlf);
-- Mail to
UTL_SMTP.write_data(Connexion, 'To: ' || EmailAddress || UTL_TCP.crlf);
-- Subject
UTL_SMTP.write_raw_data(Connexion, utl_raw.cast_to_raw('Subject:' || Subject_));
UTL_SMTP.WRITE_DATA(Connexion, UTL_TCP.CRLF);
-- Message html
UTL_SMTP.write_data(Connexion, '--' || l_boundary || UTL_TCP.crlf);
UTL_SMTP.write_data(Connexion, 'Content-Type: text/html; charset="UTF-8"' || UTL_TCP.crlf || UTL_TCP.crlf);
UTL_SMTP.write_raw_data(Connexion, utl_raw.cast_to_raw(MessageInHTML));
UTL_SMTP.write_data(Connexion, UTL_TCP.crlf || UTL_TCP.crlf);
UTL_SMTP.write_data(Connexion, '--' || l_boundary || '--' || UTL_TCP.crlf);
UTL_SMTP.close_data(Connexion);
UTL_SMTP.quit(Connexion);
end;
Basically here is the answer :
I combined two things :
Basically I created a procedure that, first creates a connexion (Part A), then loops over my query to send the emails (Part B), and finally closes the connection (Part C).
This procedure is parametrized such that it runs only on a part of the query so that I can use multithreading. For example to run on 3 threads, I added a condition in my query like :
(identifier is a numerical primary key...)
Then I insert this procedure in different jobs to run it in several threads.
There is a watchout here is that, I don't know if there is a connection maximum life time at the smtp server level. So I'm using the connection for 50 mails only, then I create a new one. So the connection time was divided by 50.
Results in performance for my case :
Connexion := UTL_SMTP.open_connection(Host, Port);
UTL_SMTP.AUTH(Connexion,KeyName,KeyValue, 'PLAIN');
UTL_SMTP.helo(Connexion, Host);
UTL_SMTP.mail(Connexion, MailFrom_);
-- Add email
UTL_SMTP.rcpt(Connexion, EmailAddress);
-- Open reader to write data
UTL_SMTP.open_data(Connexion);
-- Date
UTL_SMTP.write_data(Connexion, 'Date: ' || TO_CHAR(SYSDATE, 'DD-MON-YYYY HH24:MI:SS') || UTL_TCP.crlf);
-- Mail to
UTL_SMTP.write_data(Connexion, 'To: ' || EmailAddress || UTL_TCP.crlf);
-- Subject
UTL_SMTP.write_raw_data(Connexion, utl_raw.cast_to_raw('Subject:' || Subject_));
UTL_SMTP.WRITE_DATA(Connexion, UTL_TCP.CRLF);
-- Message html
UTL_SMTP.write_data(Connexion, '--' || l_boundary || UTL_TCP.crlf);
UTL_SMTP.write_data(Connexion, 'Content-Type: text/html; charset="UTF-8"' || UTL_TCP.crlf || UTL_TCP.crlf);
UTL_SMTP.write_raw_data(Connexion, utl_raw.cast_to_raw(MessageInHTML));
UTL_SMTP.write_data(Connexion, UTL_TCP.crlf || UTL_TCP.crlf);
UTL_SMTP.write_data(Connexion, '--' || l_boundary || '--' || UTL_TCP.crlf);
UTL_SMTP.close_data(Connexion);
UTL_SMTP.quit(Connexion);