oracle-databaseplsqlsmtp

How to speed up sending emails via Oracle PL/SQL?


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;

Solution

  • 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 :

    A part : Create the connection

        Connexion := UTL_SMTP.open_connection(Host, Port);
    
        UTL_SMTP.AUTH(Connexion,KeyName,KeyValue, 'PLAIN');
        UTL_SMTP.helo(Connexion, Host);
    

    B part : Send the email (main loop)

        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);
    

    C part : Close the connection

        UTL_SMTP.quit(Connexion);