Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Oracle Новый топик    Ответить
Топик располагается на нескольких страницах: 1 2 3 4 5 6 7 8 9 10 11      [все]
 Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
В долгих поисках рабочего решения так и не смог найти ничего ценного.
Пришлось почитать RFC и написать свое. Надеюсь кому-нибудь пригодится.
Пакет позволяет добавлять несколько вложений, что немаловажно - так это включая бинарники.
Возможно, кто-нибудь в благодарность поможет мне усовершенствовать пакет такими вещами как авторизация, или оптимизация. Пользуйтесь ;)

CREATE OR REPLACE PACKAGE MAIL_PKG IS
-- --------------------------------------------------------------------------
-- Name         : MAIL_PKG
-- Author       : Nekrasov Alexander
-- Description  : Mail package, send email with attachments
-- Ammedments   :
--   When         Who         What
--   ===========  ==========  =================================================
--   22-JAN-2010  Nekrasov A.  Initial Creation
-- --------------------------------------------------------------------------

/* EXAMPLE:

    BEGIN
	 MAIL_PKG.ADD_ATTACHMENT( 'ODPDIR'
							 ,'picture.gif'
							 ,'image/gif'
							);
	 MAIL_PKG.SEND( mailto => 'a.nekrasov@yourserver.ru'
	              , subject => 'Test subject'
				  , message => 'Some <b>bold</b> message!'
				  , mailfrom => 'no-reply@yourserver.ru'
                  , mimetype => 'text/html'
				  , sendername => 'Alert system'
				  , recipientname => 'Dear user'
	              );
	END;
*/

 -- SET_MAILSERVER:
 --  Set up mail server for send emails. Default Localhost
 -- IN
 -- MAILSERVER is ip or url of mail server
 -- MAILPORT is port for mail server. Default 25
 PROCEDURE SET_MAILSERVER ( mailserver varchar2
                          , mailport number default 25
                          );						  
						   						  
 -- ENCODE:
 --  Encodes string to email compatible view
 -- IN
 -- STR is string to convert
 -- TP is type of convert:
 --    B - is base64 encoding
 FUNCTION ENCODE( str IN VARCHAR2
                , tp IN VARCHAR2 DEFAULT 'B') RETURN VARCHAR2;

 -- PREPARE
 --  Prepare configs for email. 
 PROCEDURE PREPARE;				
				
 -- ADD_ATTACHMENT
 --  Add attachment to attachments list to email
 -- IN
 -- DIRNAME is logical link to access physical directories of server. See DBA_DIRECTORIES table
 -- FILENAME is name of file to attach
 -- MIMETYPE is mime-type for sended file
 -- NAME is name for attached file for email. Default eq FILENAME
 PROCEDURE ADD_ATTACHMENT ( dirname IN varchar2
                          , filename IN varchar2
						  , mimetype IN varchar2 DEFAULT 'text/plain'
                          , name IN varchar2 DEFAULT NULL
                           );
 -- SEND
 --  Send email with attachments to recipient
 -- IN
 -- MAILTO is email address of recipient
 -- SUBJECT is subject of email
 -- MESSAGE is message of email
 -- MIMETYPE is mime-type of message. Available values is 'text/plain' and 'text/html'
 -- SENDERNAME is mail-sender name
 -- RECIPIENTNAME is name of recipient 
 PROCEDURE SEND ( mailto IN VARCHAR2
				, subject IN VARCHAR2
				, message IN VARCHAR2
                , mailfrom IN VARCHAR2
				, mimetype IN VARCHAR2 DEFAULT 'text/plain'
				, sendername IN VARCHAR2 DEFAULT NULL
				, recipientname IN VARCHAR2 DEFAULT NULL
                );
END MAIL_PKG;
/
CREATE OR REPLACE PACKAGE BODY MAIL_PKG
IS

 mailserver VARCHAR2(30):='localhost';
 mailport INTEGER:=25;
 type attach_row is record ( dirname varchar2(30)
                           , filename  varchar2(30)
                           , name  varchar2(30)
						   , mimetype varchar2(30)
                           );
 type attach_list is table of attach_row;
 attachments attach_list;
 PROCEDURE SET_MAILSERVER ( mailserver varchar2
                          , mailport number default 25
                          ) IS
 BEGIN
  MAIL_PKG.mailserver := mailserver;
  MAIL_PKG.mailport := mailport;
 END;
 
 FUNCTION ENCODE(str IN VARCHAR2, tp IN VARCHAR2 DEFAULT 'B') RETURN VARCHAR2 IS
 BEGIN
   IF tp='B' THEN
     RETURN '=?windows-1251?B?'|| UTL_RAW.cast_to_varchar2(UTL_ENCODE.base64_encode(UTL_RAW.cast_to_raw (CONVERT (str, 'CL8MSWIN1251'))))|| '?=';
   ELSE
     RETURN str;
   END IF;
 END;

 PROCEDURE PREPARE
 IS
 BEGIN
   MAIL_PKG.attachments:=MAIL_PKG.attach_list(); 
 END;
 
 
 PROCEDURE ADD_ATTACHMENT ( dirname IN varchar2
                          , filename IN varchar2
						  , mimetype IN varchar2 DEFAULT 'text/plain'
                          , name IN varchar2 DEFAULT NULL
                           )
 IS
  v_fl BFILE :=BFILENAME(dirname,filename);
 BEGIN
   IF DBMS_LOB.FILEEXISTS (v_fl)=1 THEN
      MAIL_PKG.attachments.extend;
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).dirname:=dirname;
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).filename:=filename;
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).name:=nvl(name,filename);
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).mimetype:=mimetype;
   ELSE
      RAISE_APPLICATION_ERROR(-20001, 'File is not exists');
   END IF;
 END;


 PROCEDURE SEND ( mailto IN VARCHAR2
				, subject IN VARCHAR2
				, message IN VARCHAR2
                , mailfrom IN VARCHAR2
				, mimetype IN VARCHAR2 DEFAULT 'text/plain'
				, sendername IN VARCHAR2 DEFAULT NULL
				, recipientname IN VARCHAR2 DEFAULT NULL								
                )
 IS
   v_Mail_Conn  utl_smtp.Connection;
   crlf         VARCHAR2(2)  := utl_tcp.CRLF; -- chr(13)||chr(10);
   boundary VARCHAR2(50) := '-----7D81B75CCC90DFRW4F7A1CBD';
   vFile BFILE;
   vRAW RAW(32767);
   amt CONSTANT BINARY_INTEGER := 48; -- 48bytes binary convert to 128bytes of base64.
   v_amt BINARY_INTEGER;
   ps BINARY_INTEGER := 1;
   v_mime VARCHAR2(30);
 BEGIN
    IF mimetype<>'text/html' and mimetype<>'text/plain' THEN
      RAISE_APPLICATION_ERROR(-20001, 'MimeType must be "text/html" or "text/plain"');
    ELSE 
      v_mime:=mimetype;	 
    END IF; 
    v_Mail_Conn := utl_smtp.Open_Connection(MAIL_PKG.mailserver, MAIL_PKG.mailport);
    utl_smtp.Helo(v_Mail_Conn,MAIL_PKG.mailserver);
    utl_smtp.Mail(v_Mail_Conn, mailfrom);
    utl_smtp.Rcpt(v_Mail_Conn, mailto);

    utl_smtp.open_data(v_Mail_Conn); -- open data sheet

	utl_smtp.write_data(v_Mail_Conn, 'Date: ' || to_char(sysdate, 'Dy, DD Mon YYYY hh24:mi:ss') || crlf);
    utl_smtp.write_data(v_Mail_Conn, 'From: ');
    utl_smtp.write_raw_data(v_Mail_Conn, utl_raw.cast_to_raw(sendername));	
    utl_smtp.write_data(v_Mail_Conn, ' <'||mailfrom ||'>' || crlf );
    utl_smtp.write_data(v_Mail_Conn, 'Subject: '|| MAIL_PKG.ENCODE(subject) || crlf );
    utl_smtp.write_data(v_Mail_Conn, 'To: ');
    utl_smtp.write_raw_data(v_Mail_Conn, utl_raw.cast_to_raw(recipientname));
    utl_smtp.write_data(v_Mail_Conn, ' <'||mailto ||'>' || crlf );

    utl_smtp.write_data(v_Mail_Conn, 'MIME-version: 1.0' || crlf );
    utl_smtp.write_data(v_Mail_Conn, 'Content-Type: multipart/mixed;'|| crlf );
    utl_smtp.write_data(v_Mail_Conn, ' boundary="'||boundary||'"'|| crlf );
    utl_smtp.write_data(v_Mail_Conn, crlf );

    --Message
    utl_smtp.write_data(v_Mail_Conn, '--'|| boundary || crlf );
    utl_smtp.write_data(v_Mail_Conn, 'Content-Type: '||v_mime||'; charset="Windows-1251"'|| crlf );
    utl_smtp.write_data(v_Mail_Conn, 'Content-Transfer-Encoding: 8bit'|| crlf );
    utl_smtp.write_data(v_Mail_Conn, crlf );
    utl_smtp.write_raw_data(v_Mail_Conn, utl_raw.cast_to_raw(message));
    utl_smtp.write_data(v_Mail_Conn, crlf );
    utl_smtp.write_data(v_Mail_Conn, crlf );

	--Attachments
	IF MAIL_PKG.attachments is not null THEN
	  FOR x IN 1 .. MAIL_PKG.attachments.count LOOP
          utl_smtp.write_data(v_Mail_Conn, '--'|| boundary || crlf );
          utl_smtp.write_data(v_Mail_Conn, 'Content-Type: '||MAIL_PKG.attachments(x).mimetype||';'|| crlf );
          utl_smtp.write_data(v_Mail_Conn, ' name="'||MAIL_PKG.attachments(x).name||'"'|| crlf );
          utl_smtp.write_data(v_Mail_Conn, 'Content-Transfer-Encoding: base64'|| crlf );
          utl_smtp.write_data(v_Mail_Conn, 'Content-Disposition: attachment;'|| crlf );
          utl_smtp.write_data(v_Mail_Conn, ' filename="'||MAIL_PKG.attachments(x).name||'"' || crlf);
          utl_smtp.write_data(v_Mail_Conn, crlf );
		  dbms_output.put_line(MAIL_PKG.attachments(x).dirname);
		  dbms_output.put_line(MAIL_PKG.attachments(x).filename);		  
		  vFile := BFILENAME(MAIL_PKG.attachments(x).dirname,MAIL_PKG.attachments(x).filename);

		  dbms_lob.fileopen(vFile, dbms_lob.file_readonly);
		  ps:=1; v_amt:=amt;
		  LOOP
		    BEGIN
		      dbms_lob.read (vFile, v_amt, ps, vRAW);
			  ps := ps + v_amt;
              utl_smtp.write_raw_data(v_Mail_Conn, UTL_ENCODE.base64_encode(vRAW));
		    EXCEPTION
              WHEN no_data_found THEN
			  EXIT;
			END;
		  END LOOP;
		  dbms_lob.fileclose(vFile);

          utl_smtp.write_data(v_Mail_Conn, crlf );
          utl_smtp.write_data(v_Mail_Conn, crlf );
	  END LOOP;
	END IF;

    -- Final Boundary
    utl_smtp.write_data(v_Mail_Conn, '--' || boundary || '--');

    utl_smtp.close_data(v_Mail_Conn);
    utl_smtp.quit(v_Mail_Conn);

	-- Clear attachments
    MAIL_PKG.attachments:=MAIL_PKG.attach_list();
		
 EXCEPTION
    WHEN OTHERS THEN
       BEGIN
         MAIL_PKG.attachments:=MAIL_PKG.attach_list();
	     utl_smtp.quit(v_Mail_Conn);
	   EXCEPTION WHEN OTHERS THEN NULL;
	   END;
	RAISE;	
 END;

BEGIN
  MAIL_PKG.attachments:=MAIL_PKG.attach_list();
END;
/

22 янв 10, 19:53    [8232242]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
Доработал пакет, убрал лишнее, сделал разбор входящих емайлов (можно отправлять на несколько емайлов), добавил приоритет письма, добавил авторизацию. Сделал необязательным адрес отправителя (по умолчанию mail@имя_сервера).

CREATE OR REPLACE PACKAGE MAIL_PKG IS
-- --------------------------------------------------------------------------
-- Name         : MAIL_PKG
-- Author       : Nekrasov Alexander
-- Description  : Mail package, send email with attachments
-- Ammedments   :
--   When         Who         What
--   ===========  ==========  =================================================
--   22-JAN-2010  Nekrasov A.  Initial Creation
-- --------------------------------------------------------------------------

/* EXAMPLE:

 1) Short text email
 
    BEGIN
      MAIL_PKG.SEND( 'username@domain.ru','Test subject', 'Some message!');
    END;

 2) Extension Email with attacments
  	
    BEGIN
	 MAIL_PKG.SET_MAILSERVER ('localhost',25);
	 MAIL_PKG.SET_AUTH ('username','password');	
	 MAIL_PKG.ADD_ATTACHMENT( 'ODPDIR','image.jpeg','image/jpeg');
	 MAIL_PKG.ADD_ATTACHMENT( 'ODPDIR','picture.gif','image/gif');
	 MAIL_PKG.SEND( mailto => 'User1 <user1@domain.ru>, User2 <user2@domain.ru>'
	             , subject => 'Test subject'
	             , message => 'Some <b>bold</b> message!'
		     , mailfrom => 'Oracle Notify <no-reply@s7.ru>'
                      , mimetype => 'text/html'
                      , priority => 1
	              );
  END;
*/

 -- SET_MAILSERVER:
 --  Set up mail server for send emails. Default Localhost
 -- IN
 -- MAILSERVER is ip or url of mail server
 -- MAILPORT is port for mail server. Default 25
 PROCEDURE SET_MAILSERVER ( mailserver varchar2
                          , mailport number default 25
                          );						  

 -- SET_AUTH
 --  Set authorization on smtp server
 -- IN
 -- AUTH_USER is authorization user
 -- AUTH_PASS is password for AUTH_USER
 -- 
 -- Execute SET_AUTH(); -- for disable authorization 						  
 PROCEDURE SET_AUTH (  auth_user varchar2 default null
                     , auth_pass varchar2 default null
                          );						  
						   						  
 -- ENCODE:
 --  Encodes string to email compatible view
 -- IN
 -- STR is string to convert
 -- TP is type of convert:
 --    B - is base64 encoding
 FUNCTION ENCODE( str IN VARCHAR2
                , tp IN VARCHAR2 DEFAULT 'B') RETURN VARCHAR2;

 -- PREPARE
 --  Prepare configs for email. 
 PROCEDURE PREPARE;				
				
 -- ADD_ATTACHMENT
 --  Add attachment to attachments list to email
 -- IN
 -- DIRNAME is logical link to access physical directories of server. See DBA_DIRECTORIES table
 -- FILENAME is name of file to attach
 -- MIMETYPE is mime-type for sended file
 -- NAME is name for attached file for email. Default eq FILENAME
 PROCEDURE ADD_ATTACHMENT ( dirname IN varchar2
                          , filename IN varchar2
						  , mimetype IN varchar2 DEFAULT 'text/plain'
                          , name IN varchar2 DEFAULT NULL
                           );
 -- SEND
 --  Send email with attachments to recipient
 -- IN
 -- MAILTO is name and email addresses of recipients ( ex. "user@domain.com"
 --       , "User Name <user@domain.com>", "User1 <user1@domain>, User2 <user2@domain>")
 -- SUBJECT is subject of email
 -- MESSAGE is message of email
 -- MAILFROM is name and email of sender. (ex. "no-reply@domain", "Notify system <no-reply@domain>")
 -- MIMETYPE is mime-type of message. Available values is 'text/plain' and 'text/html'
 -- PRIORITY is priority of mail (1 - High, 2 - Highest, 3 - Normal, 4 - Lowest, 5 - Low)
 PROCEDURE SEND ( mailto IN VARCHAR2
				, subject IN VARCHAR2
				, message IN VARCHAR2
                , mailfrom IN VARCHAR2 DEFAULT NULL
				, mimetype IN VARCHAR2 DEFAULT 'text/plain'
				, priority IN NUMBER DEFAULT NULL
                );
END MAIL_PKG;
/

CREATE OR REPLACE PACKAGE BODY MAIL_PKG
IS

 mailserver VARCHAR2(30):='localhost';
 mailport INTEGER:=25;
 auth_user VARCHAR2(50);
 auth_pass VARCHAR2(50);
 type attach_row is record ( dirname varchar2(30)
                           , filename  varchar2(30)
                           , name  varchar2(30)
						   , mimetype varchar2(30)
                           );
 type attach_list is table of attach_row;
 attachments attach_list;
 
 type rcpt_row is record ( rcptname varchar2(50)
                     , rcptmail varchar2(30)
					 );
 type rcpt_list is table of rcpt_row;
					 
 PROCEDURE SET_MAILSERVER ( mailserver varchar2
                          , mailport number default 25
                          ) IS
 BEGIN
  MAIL_PKG.mailserver := mailserver;
  MAIL_PKG.mailport := mailport;
 END;
 
 PROCEDURE SET_AUTH (  auth_user varchar2 default null
                     , auth_pass varchar2 default null
                          ) IS
 BEGIN
   MAIL_PKG.auth_user := auth_user;
   MAIL_PKG.auth_pass := auth_pass;
 END;						    						  						  
 
 FUNCTION ENCODE(str IN VARCHAR2, tp IN VARCHAR2 DEFAULT 'B') RETURN VARCHAR2 IS
 BEGIN
   IF tp='B' THEN
     RETURN '=?windows-1251?B?'|| UTL_RAW.cast_to_varchar2(UTL_ENCODE.base64_encode(UTL_RAW.cast_to_raw (CONVERT (str, 'CL8MSWIN1251'))))|| '?=';
   ELSE
     RETURN str;
   END IF;
 END;

 PROCEDURE PREPARE
 IS
 BEGIN
   MAIL_PKG.attachments:=MAIL_PKG.attach_list(); 
 END;
 
 
 PROCEDURE ADD_ATTACHMENT ( dirname IN varchar2
                          , filename IN varchar2
						  , mimetype IN varchar2 DEFAULT 'text/plain'
                          , name IN varchar2 DEFAULT NULL
                           )
 IS
  v_fl BFILE :=BFILENAME(dirname,filename);
 BEGIN
   IF DBMS_LOB.FILEEXISTS (v_fl)=1 THEN
      MAIL_PKG.attachments.extend;
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).dirname:=dirname;
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).filename:=filename;
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).name:=nvl(name,filename);
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).mimetype:=mimetype;
   ELSE
      RAISE_APPLICATION_ERROR(-20001, 'File is not exists');
   END IF;
 END;

 FUNCTION CREATE_RCPT_LIST(mailto IN VARCHAR2) RETURN MAIL_PKG.rcpt_list IS
  v_mailto VARCHAR2(4096) := replace(mailto,';',',')||',';
  pntr INTEGER;
  buf VARCHAR2(50);
  rcptmail VARCHAR2(30);
  rcptlist MAIL_PKG.rcpt_list:=MAIL_PKG.rcpt_list();
 BEGIN
  FOR maxrcptnts IN 1..50
  LOOP
     pntr:=INSTR(v_mailto,','); buf := substr(v_mailto,1,pntr-1);
     IF pntr>0 THEN 
	   IF INSTR(buf,'<')>0 AND INSTR(buf,'>')>0 THEN
	     rcptmail:= SUBSTR(buf,INSTR(buf,'<')+1,INSTR(SUBSTR(buf,INSTR(buf,'<')+1),'>')-1);
		 IF rcptmail IS NOT NULL THEN 
	        rcptlist.extend;
		    rcptlist(rcptlist.count).rcptmail := rcptmail;
		    rcptlist(rcptlist.count).rcptname := TRIM(SUBSTR(buf,1,INSTR(buf,'<')-1));
	     END IF;		
       ELSE
	     rcptmail := TRIM(buf);
		 IF rcptmail IS NOT NULL THEN
           rcptlist.extend;
		   rcptlist(rcptlist.count).rcptmail:= rcptmail;		 
		 END IF;	 
	   END IF; 
	 ELSE
	   EXIT;
	 END IF;
	 v_mailto := substr(v_mailto,pntr+1);        
   END LOOP;
   RETURN rcptlist;
 END;

 PROCEDURE SEND ( mailto IN VARCHAR2
				, subject IN VARCHAR2
				, message IN VARCHAR2
                , mailfrom IN VARCHAR2 DEFAULT NULL
				, mimetype IN VARCHAR2 DEFAULT 'text/plain'
				, priority IN NUMBER DEFAULT NULL												
                )
 IS
   v_Mail_Conn  utl_smtp.Connection;
   crlf         VARCHAR2(2)  := utl_tcp.CRLF; -- chr(13)||chr(10);
   boundary VARCHAR2(50) := '-----7D81B75CCC90DFRW4F7A1CBD';
   vFile BFILE;
   vRAW RAW(32767);
   amt CONSTANT BINARY_INTEGER := 48; -- 48bytes binary convert to 128bytes of base64.
   v_amt BINARY_INTEGER;
   ps BINARY_INTEGER := 1;
   v_mime VARCHAR2(30);
   reply UTL_SMTP.REPLY;
   replies UTL_SMTP.REPLIES;
   rcptlist MAIL_PKG.rcpt_list;
   sndr MAIL_PKG.rcpt_row;
 BEGIN
    rcptlist:=create_rcpt_list(mailto);
	IF rcptlist.count=0 THEN
      RAISE_APPLICATION_ERROR(-20001, 'Recipients requered');	
	END IF;
    IF mimetype<>'text/html' and mimetype<>'text/plain' THEN
      RAISE_APPLICATION_ERROR(-20001, 'MimeType must be "text/html" or "text/plain"');
    ELSE 
      v_mime:=mimetype;	 
    END IF; 
    v_Mail_Conn := utl_smtp.Open_Connection(MAIL_PKG.mailserver, MAIL_PKG.mailport);
    replies:=utl_smtp.Ehlo(v_Mail_Conn,MAIL_PKG.mailserver);
	
	if create_rcpt_list(mailfrom).count>0 then
	  sndr := create_rcpt_list(mailfrom)(1);
	else 
	  sndr := create_rcpt_list( 'mail@' || UTL_INADDR.GET_HOST_NAME )(1); -- host from oracle-server
	  -- sndr := create_rcpt_list( 'mail@' || substr(replies(1).text,1,instr(replies(1).text,' ')-1))(1); -- Addr from ehlo answer
    end if;	
	
    if mail_pkg.auth_user is not null then
       for x IN 1 .. replies.count loop
 	     IF INSTR(replies(x).text,'AUTH')>0 then -- If server supply authorization
            utl_smtp.command(v_Mail_Conn, 'AUTH LOGIN');
            utl_smtp.command(v_Mail_Conn,utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(auth_user))));
            utl_smtp.command(v_Mail_Conn,utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(auth_pass))));    		 
		 END IF;
	   end loop;  	
    end if;	
	
    utl_smtp.Mail(v_Mail_Conn, sndr.rcptmail);
    FOR rcpts IN 1 .. rcptlist.count
	LOOP
	  utl_smtp.Rcpt(v_Mail_Conn, rcptlist(rcpts).rcptmail);
	END LOOP;

    utl_smtp.open_data(v_Mail_Conn); -- open data sheet

	utl_smtp.write_data(v_Mail_Conn, 'Date: ' || to_char(sysdate, 'Dy, DD Mon YYYY hh24:mi:ss') || crlf);
    utl_smtp.write_data(v_Mail_Conn, 'From: ');
    utl_smtp.write_raw_data(v_Mail_Conn, utl_raw.cast_to_raw(sndr.rcptname));	
    utl_smtp.write_data(v_Mail_Conn, ' <'||sndr.rcptmail ||'>' || crlf );
    utl_smtp.write_data(v_Mail_Conn, 'Subject: '|| MAIL_PKG.ENCODE(subject) || crlf );
    utl_smtp.write_data(v_Mail_Conn, 'To: ');
    utl_smtp.write_raw_data(v_Mail_Conn, utl_raw.cast_to_raw(mailto));
    utl_smtp.write_data(v_Mail_Conn, crlf );
		
	IF priority IS NOT NULL and priority BETWEEN 1 AND 5 THEN
      utl_smtp.write_data(v_Mail_Conn, 'X-Priority: ' || priority || crlf );
	END IF;
    utl_smtp.write_data(v_Mail_Conn, 'MIME-version: 1.0' || crlf );
    utl_smtp.write_data(v_Mail_Conn, 'Content-Type: multipart/mixed;'|| crlf );
    utl_smtp.write_data(v_Mail_Conn, ' boundary="'||boundary||'"'|| crlf );
    utl_smtp.write_data(v_Mail_Conn, crlf );

    --Message
    utl_smtp.write_data(v_Mail_Conn, '--'|| boundary || crlf );
    utl_smtp.write_data(v_Mail_Conn, 'Content-Type: '||v_mime||'; charset="Windows-1251"'|| crlf );
    utl_smtp.write_data(v_Mail_Conn, 'Content-Transfer-Encoding: 8bit'|| crlf );
    utl_smtp.write_data(v_Mail_Conn, crlf );
    utl_smtp.write_raw_data(v_Mail_Conn, utl_raw.cast_to_raw(message));
    utl_smtp.write_data(v_Mail_Conn, crlf );
    utl_smtp.write_data(v_Mail_Conn, crlf );

	--Attachments
	IF MAIL_PKG.attachments is not null THEN
	  FOR x IN 1 .. MAIL_PKG.attachments.count LOOP
          utl_smtp.write_data(v_Mail_Conn, '--'|| boundary || crlf );
          utl_smtp.write_data(v_Mail_Conn, 'Content-Type: '||MAIL_PKG.attachments(x).mimetype||';'|| crlf );
          utl_smtp.write_data(v_Mail_Conn, ' name="'||MAIL_PKG.attachments(x).name||'"'|| crlf );
          utl_smtp.write_data(v_Mail_Conn, 'Content-Transfer-Encoding: base64'|| crlf );
          utl_smtp.write_data(v_Mail_Conn, 'Content-Disposition: attachment;'|| crlf );
          utl_smtp.write_data(v_Mail_Conn, ' filename="'||MAIL_PKG.attachments(x).name||'"' || crlf);
          utl_smtp.write_data(v_Mail_Conn, crlf );		  
		  vFile := BFILENAME(MAIL_PKG.attachments(x).dirname,MAIL_PKG.attachments(x).filename);
		  dbms_lob.fileopen(vFile, dbms_lob.file_readonly);
		  ps:=1; v_amt:=amt;
		  LOOP
		    BEGIN
		      dbms_lob.read (vFile, v_amt, ps, vRAW);
			  ps := ps + v_amt;
              utl_smtp.write_raw_data(v_Mail_Conn, UTL_ENCODE.base64_encode(vRAW));
		    EXCEPTION
              WHEN no_data_found THEN
			  EXIT;
			END;
		  END LOOP;
		  dbms_lob.fileclose(vFile);

          utl_smtp.write_data(v_Mail_Conn, crlf );
          utl_smtp.write_data(v_Mail_Conn, crlf );
	  END LOOP;
	END IF;

    -- Final Boundary
    utl_smtp.write_data(v_Mail_Conn, '--' || boundary || '--');

    utl_smtp.close_data(v_Mail_Conn);
    utl_smtp.quit(v_Mail_Conn);

	-- Clear attachments
    MAIL_PKG.attachments:=MAIL_PKG.attach_list();
		
 EXCEPTION
    WHEN OTHERS THEN
       BEGIN
         MAIL_PKG.attachments:=MAIL_PKG.attach_list();
		 utl_smtp.rset(v_Mail_Conn);
	     utl_smtp.quit(v_Mail_Conn);
	   EXCEPTION WHEN OTHERS THEN NULL;
	   END;
	RAISE;	
 END;

BEGIN
  MAIL_PKG.attachments:=MAIL_PKG.attach_list();
END;
/

24 янв 10, 09:32    [8235643]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
comphead
Member

Откуда: Киев
Сообщений: 3390
chameleon82,

спс )
2 мар 10, 11:23    [8416800]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
tesaq
Member

Откуда:
Сообщений: 2
это ох какое спсб
------------- свЕдение данных в таблицу уже есть СЕКРЕТНО ---
2 мар 10, 11:34    [8416888]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
comphead
Member

Откуда: Киев
Сообщений: 3390
chameleon82,

Кстати, в пакете решена проблема того что тело сообщения в UTL_SMTP должно быть не больше 32K?
9 мар 10, 17:38    [8451163]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
comphead
chameleon82,

Кстати, в пакете решена проблема того что тело сообщения в UTL_SMTP должно быть не больше 32K?


Кстати не проверял ) Я тут еще подладил пакет на длинные названия в заголовке. Проверю, если что исправлю, обновлю пост :)
1 апр 10, 12:13    [8564257]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
Ura!
Member

Откуда:
Сообщений: 273
Правильно понимаю, что файлы для атачментов должны лежать на сервере?
И ещё вопрос, цифровой подписью не баловались? т.е. перед отправкой письма подписать его цифровой подписью.
1 апр 10, 14:54    [8565912]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
Ura!
Правильно понимаю, что файлы для атачментов должны лежать на сервере?
И ещё вопрос, цифровой подписью не баловались? т.е. перед отправкой письма подписать его цифровой подписью.

Да. Файлы должны быть на сервере в одной из директорий select * from all_directories, туда их при необходимости можно скопировать.
Размер и количество отправляемых файлов неограничены (ну по крайней мере можно отправить сразу несколько картинок по несколько мегабайт или несколько больших отчетов одновременно).
Цифровая подпись, это чтото интересное. Сомневаюсь, что здесь такое возможно, т.к. письмо отдается смтп серверу последовательно (хотя если его сначала сохранить в blob, то может и получится). Хотя если сможете доработать пакет, было бы интересно посмотреть на реализацию :)
6 апр 10, 08:22    [8583246]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
aure
Member

Откуда:
Сообщений: 9
chameleon82
В долгих поисках рабочего решения так и не смог найти ничего ценного.
Пришлось почитать RFC и написать свое. Надеюсь кому-нибудь пригодится.
Пакет позволяет добавлять несколько вложений, что немаловажно - так это включая бинарники.
Возможно, кто-нибудь в благодарность поможет мне усовершенствовать пакет такими вещами как авторизация, или оптимизация. Пользуйтесь ;)
[/src]


Спасибо! ;)
21 май 10, 10:45    [8811723]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
d.nemolchev
Member

Откуда: Кустанай
Сообщений: 293
chameleon82,

а JavaMail чем Вас не устроил?
22 май 10, 13:37    [8818119]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
d.nemolchev
Member

Откуда: Кустанай
Сообщений: 293
PS Сразу с PL/SQL-оберткой
22 май 10, 13:45    [8818123]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
andrey_anonymous
Member

Откуда: Москва
Сообщений: 15996
Сразу можно отметить, что хардкодить в такие пакеты ansi1251 - не очень разумная идея.
Даже если Вы не верите что Ваше детище пригодится кому-нибудь в просвещенной Европе, то подумйте хотя бы о мультиязычных текстах в рамках таможенного союза :)
22 май 10, 15:19    [8818339]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
IgorD
Member

Откуда: Киев
Сообщений: 225
chameleon82 - СПАСИБО!

Внес незначительные изменение в авторизацию в фрагменте кода, добавив exit
    if mail_pkg.auth_user is not null then
       for x IN 1 .. replies.count loop
 	     IF INSTR(replies(x).text,'AUTH')>0 then -- If server supply authorization
            utl_smtp.command(v_Mail_Conn, 'AUTH LOGIN');
            utl_smtp.command(v_Mail_Conn,utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(auth_user))));
            utl_smtp.command(v_Mail_Conn,utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(auth_pass))));    		 
                 exit;
		 END IF;
	   end loop;  	
    end if;	


В моем случае в replies(x).text фраза 'AUTH' встречалась дважды, что вызывало ошибку при повторной авторизации. Еще планирую добавить к пакету таблицу лог, в которой писать отправлено/не отравлено сообщение, когда и т.п. Нужно для автоматической работы в джобах и т.п.
25 май 10, 16:26    [8831651]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
dba123
Member

Откуда:
Сообщений: 962
chameleon82,

еще предложение

менять имена границ подразделов(boundary), например

S7RUMailPart-001-xxxxxxxx-xxxxxxxxxxxxxxxxx
S7RUMailPart-002-xxxxxxxx-xxxxxxxxxxxxxxxxx

где ххх может быть счетчиком, уникальным идентификатором, цифровой сверткой/подписью и т.д.
и тебе учет отправленных и сормовцам метки :)
25 май 10, 16:56    [8831964]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
d.nemolchev
chameleon82,

а JavaMail чем Вас не устроил?

Хотелось чисто PL/SQL-ное решение, тем более оно не такое сложное. Да и если следовать словам Томаса Кайта - "зачем использовать java, если можно сделать на pl/sql?". Единтсвтенное пока, что тут может пригодиться из java при отправке письма - это архивирование вложений (но это можно сделать и другими средствами).


andrey_anonymous
Сразу можно отметить, что хардкодить в такие пакеты ansi1251 - не очень разумная идея.
Даже если Вы не верите что Ваше детище пригодится кому-нибудь в просвещенной Европе, то подумйте хотя бы о мультиязычных текстах в рамках таможенного союза :)


пакет собран на коленке ))) надо проработать этот вопрос

IgorD
chameleon82 - СПАСИБО!

Внес незначительные изменение в авторизацию в фрагменте кода, добавив exit

И вам спасибо ;)

dba123
chameleon82,

еще предложение - менять имена границ подразделов(boundary)
26 май 10, 07:54    [8834002]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
dba123
chameleon82,

еще предложение

менять имена границ подразделов(boundary), например

S7RUMailPart-001-xxxxxxxx-xxxxxxxxxxxxxxxxx
S7RUMailPart-002-xxxxxxxx-xxxxxxxxxxxxxxxxx

где ххх может быть счетчиком, уникальным идентификатором, цифровой сверткой/подписью и т.д.
и тебе учет отправленных и сормовцам метки :)


надо обдумать как это сделать. идея интересная. Думаю, можно внедрить допнастройками пакета. А вот где хранить счетчик? создавать ради этого сиквенс???

---

Обновил пакет. Убрал немного мусора, перевел все на UTF-8 (протестил на бате и аутлуке), исправил ошибку с длинным именем заголовка письма и именами отправителей/получателей и что-то еще по мелочи, и замечание от IgorD. Вот моя последняя версия )

CREATE OR REPLACE PACKAGE MAIL_PKG IS
-- --------------------------------------------------------------------------
-- Name         : MAIL_PKG
-- Author       : Nekrasov Alexander
-- Description  : Mail package, send email with attachments
-- Ammedments   :
--   When         Who         What
--   ===========  ==========  =================================================
--   22-JAN-2010  Nekrasov A.  Initial Creation
--   26-MAY-2010  Nekrasov A.  Update package bugs
-- --------------------------------------------------------------------------

/* EXAMPLE:

 1) Short text email

    BEGIN
      MAIL_PKG.SEND( 'a.ivanov@yourcomany.ru','Test subject', 'Some message!');
	END;

 2) Extension Email with attacments

    BEGIN
	 MAIL_PKG.SET_MAILSERVER ('localhost',25);
	 MAIL_PKG.SET_AUTH ('a.nekrasov','password');
	 MAIL_PKG.ADD_ATTACHMENT( 'ODPDIR'
							 ,'girl3d.jpeg'
							 ,'image/jpeg'
							);
	 MAIL_PKG.SEND( mailto => 'A. Ivanov <a.ivanov@yourcomany.ru>, O.Petrov <o.petrov@yourcompany.ru>'
	              , subject => 'Test subject'
				  , message => 'Some <b>bold</b> message!'
				  , mailfrom => 'Oracle Notify <no-reply@yourcompany.ru>'
                  , mimetype => 'text/html'
				  , priority => 1
	              );
	END;
*/

 -- SET_MAILSERVER:
 --  Set up mail server for send emails. Default Localhost
 -- IN
 -- MAILSERVER is ip or url of mail server
 -- MAILPORT is port for mail server. Default 25
 PROCEDURE SET_MAILSERVER ( mailserver varchar2
                          , mailport number default 25
                          );

 -- SET_AUTH
 --  Set authorization on smtp server
 -- IN
 -- AUTH_USER is authorization user
 -- AUTH_PASS is password for AUTH_USER
 --
 -- Execute SET_AUTH(); -- for disable authorization
 PROCEDURE SET_AUTH (  auth_user varchar2 default null
                     , auth_pass varchar2 default null
                          );

 -- ENCODE:
 --  Encodes string to email compatible view
 -- IN
 -- STR is string to convert
 -- TP is type of convert:
 --    B - is base64 encoding
 FUNCTION ENCODE( str IN VARCHAR2
                , tp IN VARCHAR2 DEFAULT 'Q') RETURN VARCHAR2;

 -- PREPARE
 --  Prepare configs for email.
 PROCEDURE PREPARE;

 -- ADD_RCPT
 --  Add recipient to recipients list exploded by  ','
 -- STR is variable with recipients
 -- RCPTMAIL is recipient mail added to STR
 -- RCPTNAME is recipient name added to STR
 -- Example: str='user1@domain.ru' rcptmail='user2@domain.ru'
 --  after => str='user1@domain.ru, user2@domain.ru'
 PROCEDURE ADD_RCPT( str IN OUT VARCHAR2
                   , rcptmail IN VARCHAR2
				   , rcptname IN VARCHAR2 DEFAULT NULL);

 -- ADD_ATTACHMENT
 --  Add attachment to attachments list to email
 -- IN
 -- DIRNAME is logical link to access physical directories of server. See DBA_DIRECTORIES table
 -- FILENAME is name of file to attach
 -- MIMETYPE is mime-type for sended file
 -- NAME is name for attached file for email. Default eq FILENAME
 PROCEDURE ADD_ATTACHMENT ( dirname IN varchar2
                          , filename IN varchar2
						  , mimetype IN varchar2 DEFAULT 'text/plain'
                          , name IN varchar2 DEFAULT NULL
                           );
 -- SEND
 --  Send email with attachments to recipient
 -- IN
 -- MAILTO is name and email addresses of recipients ( ex. "user@domain.com"
 --       , "User Name <user@domain.com>", "User1 <user1@domain>, User2 <user2@domain>")
 -- SUBJECT is subject of email
 -- MESSAGE is message of email
 -- MAILFROM is name and email of sender. (ex. "no-reply@domain", "Notify system <no-reply@domain>")
 -- MIMETYPE is mime-type of message. Available values is 'text/plain' and 'text/html'
 -- PRIORITY is priority of mail (1 - High, 2 - Highest, 3 - Normal, 4 - Lowest, 5 - Low)
 PROCEDURE SEND ( mailto IN VARCHAR2
				, subject IN VARCHAR2
				, message IN VARCHAR2
                , mailfrom IN VARCHAR2 DEFAULT NULL
				, mimetype IN VARCHAR2 DEFAULT 'text/plain'
				, priority IN NUMBER DEFAULT NULL
                );
END MAIL_PKG;
/

CREATE OR REPLACE PACKAGE BODY MAIL_PKG
IS

 mailserver VARCHAR2(30):='localhost';
 mailport INTEGER:=25;
 auth_user VARCHAR2(50);
 auth_pass VARCHAR2(50);
 crlf         VARCHAR2(2)  := utl_tcp.CRLF; -- chr(13)||chr(10);

 type attach_row is record ( dirname varchar2(30)
                           , filename  varchar2(30)
                           , name  varchar2(30)
						   , mimetype varchar2(30)
                           );
 type attach_list is table of attach_row;
 attachments attach_list;

 type rcpt_row is record ( rcptname varchar2(100)
                     , rcptmail varchar2(50)
					 );
 type rcpt_list is table of rcpt_row;

 PROCEDURE SET_MAILSERVER ( mailserver varchar2
                          , mailport number default 25
                          ) IS
 BEGIN
  MAIL_PKG.mailserver := mailserver;
  MAIL_PKG.mailport := mailport;
 END;

 PROCEDURE SET_AUTH (  auth_user varchar2 default null
                     , auth_pass varchar2 default null
                          ) IS
 BEGIN
   MAIL_PKG.auth_user := auth_user;
   MAIL_PKG.auth_pass := auth_pass;
 END;

 FUNCTION ENCODE(str IN VARCHAR2, tp IN VARCHAR2 DEFAULT 'Q') RETURN VARCHAR2 IS
 BEGIN
   IF tp='B' THEN
     RETURN '=?utf-8?b?'|| UTL_RAW.cast_to_varchar2(UTL_ENCODE.base64_encode(UTL_RAW.cast_to_raw (CONVERT (SUBSTR(str,1,24), 'UTF8'))))|| '?='
	     || CASE WHEN SUBSTR(str,25) IS NOT NULL THEN crlf || ' '|| ENCODE(SUBSTR(str,25),tp) END;
   ELSIF tp='Q' THEN
     RETURN '=?utf-8?q?' || UTL_RAW.cast_to_varchar2(utl_encode.QUOTED_PRINTABLE_ENCODE(utl_raw.cast_to_raw(CONVERT (SUBSTR(str,1,8), 'UTF8') ))) || '?='
	     || CASE WHEN SUBSTR(str,9) IS NOT NULL THEN crlf || ' '|| ENCODE(SUBSTR(str,9),tp) END;
   ELSE
     RETURN str;
   END IF;
 END;

 PROCEDURE PREPARE
 IS
 BEGIN
   MAIL_PKG.attachments:=MAIL_PKG.attach_list();
 END;

 PROCEDURE ADD_RCPT( str IN OUT VARCHAR2
                   , rcptmail IN VARCHAR2
				   , rcptname IN VARCHAR2 DEFAULT NULL) IS
  rcpt varchar2(255);
 BEGIN
  rcpt:=CASE WHEN rcptname is null THEN
          rcptmail
		ELSE
		  trim(replace(replace(rcptname,',',' '),';',' '))||' <'|| rcptmail ||'>'
		END;
  IF trim(str) is NULL THEN
     str :=  trim(rcpt);
  ELSE
     str := str||', '||trim(rcpt);
  END IF;
 END;

 PROCEDURE ADD_ATTACHMENT ( dirname IN varchar2
                          , filename IN varchar2
						  , mimetype IN varchar2 DEFAULT 'text/plain'
                          , name IN varchar2 DEFAULT NULL
                           )
 IS
  v_fl BFILE :=BFILENAME(dirname,filename);
 BEGIN
   IF DBMS_LOB.FILEEXISTS (v_fl)=1 THEN
      MAIL_PKG.attachments.extend;
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).dirname:=dirname;
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).filename:=filename;
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).name:=nvl(name,filename);
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).mimetype:=mimetype;
   ELSE
      RAISE_APPLICATION_ERROR(-20001, 'File is not exists');
   END IF;
 END;

 FUNCTION CREATE_RCPT_LIST(mailto IN VARCHAR2) RETURN MAIL_PKG.rcpt_list IS
  v_mailto VARCHAR2(4096) := replace(mailto,';',',')||',';
  pntr INTEGER;
  buf VARCHAR2(255);
  rcptmail VARCHAR2(255);
  rcptlist MAIL_PKG.rcpt_list:=MAIL_PKG.rcpt_list();
 BEGIN
  FOR maxrcptnts IN 1..50
  LOOP
     pntr:=INSTR(v_mailto,','); buf := substr(v_mailto,1,pntr-1);
     IF pntr>0 THEN
	   IF INSTR(buf,'<')>0 AND INSTR(buf,'>')>0 THEN
	     rcptmail:= SUBSTR(buf,INSTR(buf,'<')+1,INSTR(SUBSTR(buf,INSTR(buf,'<')+1),'>')-1);
		 IF rcptmail IS NOT NULL THEN
	        rcptlist.extend;
		    rcptlist(rcptlist.count).rcptmail := TRIM(rcptmail);
		    rcptlist(rcptlist.count).rcptname := TRIM(SUBSTR(buf,1,INSTR(buf,'<')-1));
	     END IF;
       ELSE
	     rcptmail := TRIM(buf);
		 IF rcptmail IS NOT NULL THEN
           rcptlist.extend;
		   rcptlist(rcptlist.count).rcptmail:= TRIM(rcptmail);
		 END IF;
	   END IF;
	 ELSE
	   EXIT;
	 END IF;
	 v_mailto := substr(v_mailto,pntr+1);
   END LOOP;
   RETURN rcptlist;
 END;

 PROCEDURE SEND ( mailto IN VARCHAR2
				, subject IN VARCHAR2
				, message IN VARCHAR2
                , mailfrom IN VARCHAR2 DEFAULT NULL
				, mimetype IN VARCHAR2 DEFAULT 'text/plain'
				, priority IN NUMBER DEFAULT NULL
                )
 IS
   v_Mail_Conn  utl_smtp.Connection;
   boundary VARCHAR2(50) := '-----7D81B75CCC90DFRW4F7A1CBD';
   vFile BFILE;
   vRAW RAW(32767);
   amt CONSTANT BINARY_INTEGER := 48; -- 48bytes binary convert to 128bytes of base64.
   v_amt BINARY_INTEGER;
   ps BINARY_INTEGER := 1;
   v_mime VARCHAR2(30);
   reply UTL_SMTP.REPLY;
   replies UTL_SMTP.REPLIES;
   rcptlist MAIL_PKG.rcpt_list;
   sndr MAIL_PKG.rcpt_row;
 BEGIN
    rcptlist:=create_rcpt_list(mailto);
	IF rcptlist.count=0 THEN
      RAISE_APPLICATION_ERROR(-20001, 'Recipients requered');
	END IF;
    IF mimetype<>'text/html' and mimetype<>'text/plain' THEN
      RAISE_APPLICATION_ERROR(-20001, 'MimeType must be "text/html" or "text/plain"');
    ELSE
      v_mime:=mimetype;
    END IF;
    v_Mail_Conn := utl_smtp.Open_Connection(MAIL_PKG.mailserver, MAIL_PKG.mailport);
    replies:=utl_smtp.Ehlo(v_Mail_Conn,MAIL_PKG.mailserver);
	if create_rcpt_list(mailfrom).count>0 then
	  sndr := create_rcpt_list(mailfrom)(1);
	else
	  sndr := create_rcpt_list( 'mail@' || UTL_INADDR.GET_HOST_NAME )(1); -- host from oracle-server
	  -- sndr := create_rcpt_list( 'mail@' || substr(replies(1).text,1,instr(replies(1).text,' ')-1))(1); -- Addr from ehlo answer
    end if;

    if mail_pkg.auth_user is not null then
       for x IN 1 .. replies.count loop
	     dbms_output.put_line(replies(x).text);
 	     IF INSTR(replies(x).text,'AUTH')>0 then -- If server supply authorization
            utl_smtp.command(v_Mail_Conn, 'AUTH LOGIN');
            utl_smtp.command(v_Mail_Conn,utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(auth_user))));
            utl_smtp.command(v_Mail_Conn,utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(auth_pass))));
			exit;
		 END IF;
	   end loop;
    end if;

    utl_smtp.Mail(v_Mail_Conn, sndr.rcptmail);
    FOR rcpts IN 1 .. rcptlist.count
	LOOP
	  utl_smtp.Rcpt(v_Mail_Conn, rcptlist(rcpts).rcptmail);
	END LOOP;

    utl_smtp.open_data(v_Mail_Conn); -- open data sheet

	utl_smtp.write_data(v_Mail_Conn, 'Date: ' || to_char(sysdate, 'Dy, DD Mon YYYY hh24:mi:ss','NLS_DATE_LANGUAGE = ''american''') || crlf);
    utl_smtp.write_data(v_Mail_Conn, 'From: ');
	if sndr.rcptname is not null then
        utl_smtp.write_data(v_Mail_Conn, MAIL_PKG.ENCODE(sndr.rcptname) ||' <'|| sndr.rcptmail || '>');
	else
        utl_smtp.write_data(v_Mail_Conn, sndr.rcptmail);
	end if;
    utl_smtp.write_data(v_Mail_Conn, crlf );
    utl_smtp.write_data(v_Mail_Conn, 'Subject: '|| MAIL_PKG.ENCODE(subject) || crlf );
    utl_smtp.write_data(v_Mail_Conn, 'To: ');
    FOR rcpts IN 1 .. rcptlist.count
	LOOP
	  if rcpts>1 then
       utl_smtp.write_data(v_Mail_Conn, ',');
	  end if;
	  if rcptlist(rcpts).rcptname is not null then
        utl_smtp.write_data(v_Mail_Conn, MAIL_PKG.ENCODE(rcptlist(rcpts).rcptname) ||' <'|| rcptlist(rcpts).rcptmail || '>');
	  else
        utl_smtp.write_data(v_Mail_Conn, rcptlist(rcpts).rcptmail);
	  end if;
	END LOOP;
    utl_smtp.write_data(v_Mail_Conn, crlf );

	IF priority IS NOT NULL and priority BETWEEN 1 AND 5 THEN
      utl_smtp.write_data(v_Mail_Conn, 'X-Priority: ' || priority || crlf );
	END IF;
    utl_smtp.write_data(v_Mail_Conn, 'MIME-version: 1.0' || crlf );
    utl_smtp.write_data(v_Mail_Conn, 'Content-Type: multipart/mixed;'|| crlf );
    utl_smtp.write_data(v_Mail_Conn, ' boundary="'||boundary||'"'|| crlf );
    utl_smtp.write_data(v_Mail_Conn, crlf );

    --Message
    utl_smtp.write_data(v_Mail_Conn, '--'|| boundary || crlf );
    utl_smtp.write_data(v_Mail_Conn, 'Content-Type: '||v_mime||'; charset="utf-8"'|| crlf );
    utl_smtp.write_data(v_Mail_Conn, 'Content-Transfer-Encoding: 8bit'|| crlf );
    utl_smtp.write_data(v_Mail_Conn, crlf );
    utl_smtp.write_raw_data(v_Mail_Conn, utl_raw.cast_to_raw(CONVERT(message,'UTF8')));
    utl_smtp.write_data(v_Mail_Conn, crlf );
    utl_smtp.write_data(v_Mail_Conn, crlf );

	--Attachments
	IF MAIL_PKG.attachments is not null THEN
	  FOR x IN 1 .. MAIL_PKG.attachments.count LOOP
          utl_smtp.write_data(v_Mail_Conn, '--'|| boundary || crlf );
          utl_smtp.write_data(v_Mail_Conn, 'Content-Type: '||MAIL_PKG.attachments(x).mimetype||';'|| crlf );
          utl_smtp.write_data(v_Mail_Conn, ' name="');
		  utl_smtp.write_raw_data(v_Mail_Conn,utl_raw.cast_to_raw(MAIL_PKG.attachments(x).name));
          utl_smtp.write_data(v_Mail_Conn, '"' || crlf);
          utl_smtp.write_data(v_Mail_Conn, 'Content-Transfer-Encoding: base64'|| crlf );
          utl_smtp.write_data(v_Mail_Conn, 'Content-Disposition: attachment;'|| crlf );
          utl_smtp.write_data(v_Mail_Conn, ' filename="' || MAIL_PKG.ENCODE(MAIL_PKG.attachments(x).name) || '"' || crlf);
          utl_smtp.write_data(v_Mail_Conn, crlf );
		  vFile := BFILENAME(MAIL_PKG.attachments(x).dirname,MAIL_PKG.attachments(x).filename);
		  dbms_lob.fileopen(vFile, dbms_lob.file_readonly);
		  ps:=1; v_amt:=amt;
		  LOOP
		    BEGIN
		      dbms_lob.read (vFile, v_amt, ps, vRAW);
			  ps := ps + v_amt;
              utl_smtp.write_raw_data(v_Mail_Conn, UTL_ENCODE.base64_encode(vRAW));
		    EXCEPTION
              WHEN no_data_found THEN
			  EXIT;
			END;
		  END LOOP;
		  dbms_lob.fileclose(vFile);

          utl_smtp.write_data(v_Mail_Conn, crlf );
          utl_smtp.write_data(v_Mail_Conn, crlf );
	  END LOOP;
	END IF;

    -- Final Boundary
    utl_smtp.write_data(v_Mail_Conn, '--' || boundary || '--');

    utl_smtp.close_data(v_Mail_Conn);
    utl_smtp.quit(v_Mail_Conn);

	-- Clear attachments
    MAIL_PKG.attachments:=MAIL_PKG.attach_list();

 EXCEPTION
    WHEN OTHERS THEN
       BEGIN
         MAIL_PKG.attachments:=MAIL_PKG.attach_list();
		 utl_smtp.rset(v_Mail_Conn);
	     utl_smtp.quit(v_Mail_Conn);
	   EXCEPTION WHEN OTHERS THEN NULL;
	   END;
	RAISE;
 END;

BEGIN
  MAIL_PKG.attachments:=MAIL_PKG.attach_list();
END;
/
26 май 10, 08:17    [8834046]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
_Ildar_
Member

Откуда: Astrakhan
Сообщений: 310
Очень интересное решение.
У меня размер сообщения больше 32Кб?

Как отправить такое сообщение?

Спасибо!
7 июн 10, 19:57    [8904812]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
вопросец
Guest
у меня всегда возникает вопрос. зачем тулить этот левый функцианал. и каким то диким извратом его реализовывать. не лучше ли потратив гораздо меньше времени по быренькому склепать службу/демон или задание шедулера/крона которое выколупает из БД необходимые данные и разошлет там чего-то. тем более что такие рассыльщики имеют свойство расползаться до монстров с тяжелой логикой.
7 июн 10, 20:13    [8904849]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
SQL*Plus
Member

Откуда: Россия, Москва
Сообщений: 7756
вопросец
у меня всегда возникает вопрос. зачем тулить этот левый функцианал. и каким то диким извратом его реализовывать. не лучше ли потратив гораздо меньше времени по быренькому склепать службу/демон или задание шедулера/крона которое выколупает из БД необходимые данные и разошлет там чего-то. тем более что такие рассыльщики имеют свойство расползаться до монстров с тяжелой логикой.
Это не "левый функционал".
Это нормальный подход программиста Oracle Database использовать штатные возможности Oracle Database.
Для этого требуется только хорошее знание PL/SQL и предлагаемых для него штатных пакетов.

Не требуются знания:
- как "по быренькому склепать службу/демон или задание шедулера/крона"
- как "выколупать из БД необходимые данные" во внешние файлы/места
- как реализовать вне БД "монстров с тяжелой логикой"
То есть не требуется никакого "дикого изврата", внешнего по отношению к БД.

Знаешь PL/SQL - пользуйся им. PL/SQL хватает практически для всего.
7 июн 10, 20:28    [8904875]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
_Ildar_
Member

Откуда: Astrakhan
Сообщений: 310
вопросец
у меня всегда возникает вопрос. зачем тулить этот левый функцианал. и каким то диким извратом его реализовывать. не лучше ли потратив гораздо меньше времени по быренькому склепать службу/демон или задание шедулера/крона которое выколупает из БД необходимые данные и разошлет там чего-то. тем более что такие рассыльщики имеют свойство расползаться до монстров с тяжелой логикой.


Вот есть несколько прог, которые запускаюся по расписанию на серваке x86 9.2.0.7
Сейчас переехал на сервак 10.2.0.4. по x64 и проги на 32 разряда не работают из-за:
Ошибка: В указанном DSN архитектура драйвера и архитектура приложения не соответствуют друг другу.
Проги x86 не хотят коннектиться к БД с помощью ODBC x64 драйвера оракла.
Если бы все было сделано средствами оракла проблем при переходе небыло.
Для меня, что одна из полезностей этого пакета именно в этом.
Переписывать под x64 конечно можно, но проц у меня не понимает такие ОС.
Пакет полезный, но тело сообщения ограничено 32 К !!!

HELP!!!! Помогите!
7 июн 10, 20:39    [8904896]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
вопросец
Guest
_Ildar_,

чтобы x86_32 прога жила под x86_64 нужен клиент x86_32

а почему же вы не протестировали работоспособность ПО прежде чем осуществлять переход? я так понимаю это продакшн. прога может упасть н только из-за того что не может в свое 32-bit адрасное пространство грузить x86_64 модули :). но может и повезти.

---

впринципе мысльвысказавшихся я понял.
7 июн 10, 20:47    [8904911]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
_Ildar_
Member

Откуда: Astrakhan
Сообщений: 310
вопросец
_Ildar_,
чтобы x86_32 прога жила под x86_64 нужен клиент x86_32

Да. Нужен, то не устанавливается клиент x86 на x64 платформу! Хоть ты тресни!

вопросец

а почему же вы не протестировали работоспособность ПО прежде чем осуществлять переход? я так понимаю это продакшн. прога может упасть н только из-за того что не может в свое 32-bit адрасное пространство грузить x86_64 модули :). но может и повезти.

Не повезло. От такого невезения и ищу решение.
Обойти бы это ограничение по размеру тела письма и все было бы ОК!
7 июн 10, 21:02    [8904951]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
вопросец
Guest
_Ildar_,

не правда ваша. клиент x86_32 работает под x86_64. (Oracle Client)
7 июн 10, 21:35    [8905015]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
andrey_anonymous
Member

Откуда: Москва
Сообщений: 15996
_Ildar_
Обойти бы это ограничение по размеру тела письма и все было бы ОК!

Шлите письма html-аттачем, как поступают все современные спамеры :)
7 июн 10, 21:37    [8905022]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
_Ildar_
Member

Откуда: Astrakhan
Сообщений: 310
andrey_anonymous
_Ildar_
Обойти бы это ограничение по размеру тела письма и все было бы ОК!

Шлите письма html-аттачем, как поступают все современные спамеры :)

Это мысль. Надо попробовать.
8 июн 10, 13:01    [8907625]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
_Ildar_
andrey_anonymous
_Ildar_
Обойти бы это ограничение по размеру тела письма и все было бы ОК!

Шлите письма html-аттачем, как поступают все современные спамеры :)

Это мысль. Надо попробовать.

Все верно, создаете аттач, делаете его типом html или txt, прикрепляете первым, затем остальные атачи. Работает безотказно. Я таким образом посылал хтмлки с картинками.
Еще, если позволите, вопрос. В каком типе переменной у Вас хранится письмо такого размера? В Clob?
По идее можно дописать пакет, на вход подавая CLOB, т.е. два метода SEND, один с варчар, второй с клоб, кому как удобнее )
23 июн 10, 18:29    [8989913]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
s_elected
Member

Откуда: Серпухов
Сообщений: 464
chameleon82,

Автору выражаю огромную благодарность !
25 июн 10, 18:05    [9004516]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
suPPLer
Member

Откуда: Харків, Україна
Сообщений: 7797
Блог
chameleon82
Вот моя последняя версия )

...
    utl_smtp.Mail(v_Mail_Conn, sndr.rcptmail);
    FOR rcpts IN 1 .. rcptlist.count
	LOOP
	  utl_smtp.Rcpt(v_Mail_Conn, rcptlist(rcpts).rcptmail);
	END LOOP;


Рекомендую перечитать в RFC 2822 раздел, касающийся синтаксиса адреса (3.4). То, что некоторые SMTP-серверы проглотят reverse-path и forward-path без обрамляющих < и >, вовсе не означает, что так сделают все.

Для пробы попробуйте отправить письмо Вашим пакетом через SMTP-сервер GMail. Получите:
555 5.5.2 Syntax error.
27 июн 10, 05:29    [9007575]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
Glum1111
Guest
автору огромное спасибо!
давно хотел разобраться с этой темой, но как всегда руки не доходили.
доработал для blob и пошагового заполнения текста сообщения, работает действительно безотказно!

но появился такой вопрос:
возможно ли отправлять сообщения на виндусовый msn messenger ?
ситуация такая что не на всех компах настроен outlook express, а необходимость оповещения не уменьшилась.

буду благодарен любой полезной информации
8 сен 10, 13:09    [9403644]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
stalker_cop
Member

Откуда:
Сообщений: 92
Всем привет!
Если кому интересно могу отписать как отправить вложение больше чем 32К!
Прикол заключается в том что необходимо закодировать в base64 blob
10 сен 10, 17:40    [9421206]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
stalker_cop
Member

Откуда:
Сообщений: 92
Используйте следующие процедуры для кодирования и декодирования в base64

{src}

PROCEDURE Encode_Base64(p_Src IN OUT NOCOPY BLOB
,p_Dst IN OUT NOCOPY BLOB) IS
c_Max_Length_Base64 CONSTANT PLS_INTEGER := 22848;
/*
c_Max_Length_Base64 НЕ МЕНЯТЬ
Она подобранна специальным образом
Исходя из следующих соображений
32767 - максимальный размер буфера что оракл может сконвертить (на выходе)
поэтому на входе необходимо подать 32767*0.7 = 22936 байт
(особенности base64 (три байта конвертятся в четыре))
Другой особенностью является то что сконвертированный текст режится на строки по 64 символа
Так как алгоритм построен просто на склейке выходных данных (после кодирования)
то необходимо основные данные резать так чтоб длинна была кратна 3 чтоб в конце не было
символов "="
Но и этого не достаточно когда обрабатываются куски входного потока то
размер обрабобтанного куска должен быть кратен 64
поэтому получаем следующее 64*3*n < 22936
путем не сложных вычислений получаем что n = 119
64*3*119 = 22848
вот так получена эта цифра
можно былобы по другому (вырезать переводы корретки а потом резать по 64 и добавлять
переводу коретки по моему это лишнее)
*/
i_Pos INTEGER := 1;
n_Amount BINARY_INTEGER := c_Max_Length_Base64;
i_Pos_w INTEGER := 1;
n_Amount_w BINARY_INTEGER;
a_Raw RAW(32767);
n_Length_Src INTEGER;
BEGIN
IF p_Src IS NOT NULL
AND Dbms_Lob.Getlength(p_Src) != 0 THEN
Dbms_lob.Createtemporary(p_Dst,FALSE);
n_Length_Src := Dbms_Lob.Getlength(p_Src);
LOOP
IF i_Pos + c_Max_Length_Base64 - 1 <= n_Length_Src THEN
n_Amount := c_Max_Length_Base64;
ELSE
n_Amount := n_Length_Src - i_Pos + 1;
END IF;
a_Raw := Utl_Encode.Base64_Encode(Dbms_Lob.Substr(p_Src, n_Amount, i_Pos));
n_Amount_w := Utl_Raw.Length(a_Raw);
Dbms_lob.Write(p_Dst, n_Amount_w, i_Pos_w, a_Raw);
i_Pos_w := n_Amount_w + i_Pos_w;
i_Pos := n_Amount + i_Pos;
EXIT WHEN i_Pos >= n_Length_Src;
END LOOP;
END IF;
END;

PROCEDURE Decode_Base64(p_Src IN OUT NOCOPY BLOB
,p_Dst IN OUT NOCOPY BLOB) IS
c_Max CONSTANT PLS_INTEGER := 32736;
/*
c_Max НЕ МЕНЯТЬ
Она подобранна специальным образом
Исходя из следующих соображений
32767 - максимальный размер буфера что оракл может сконвертить (на входе)
на выходе получится примерно 32767*0.7 = 22936 байт
(особенности base64 (три байта конвертятся в четыре))
Другой особенностью является то что сконвертированный текст режится на строки по 64 символа
Так как алгоритм построен просто на склейке выходных данных (после декодирования)
то необходимо основные данные резать так чтоб длинна была кратна 4
Но и этого не достаточно когда обрабатываются куски входного потока
они порезаны по строчкам длинной 66 символов (64 основных и 2 символа перевода корректки 13+10)
поэтому получаем следующее 66*4*n < 32767
путем не сложных вычислений получаем что n = 119
66*4*124 = 32736
вот так получена эта цифра
*/

a_Part RAW(32764);
i_Pos INTEGER := 1;
n_Amount BINARY_INTEGER := c_Max;
i_Pos_w INTEGER := 1;
n_Amount_w BINARY_INTEGER;
n_Length_Src INTEGER;
BEGIN
IF p_Src IS NOT NULL
AND Dbms_Lob.Getlength(p_Src) != 0 THEN
Dbms_lob.Createtemporary(p_Dst,FALSE);
n_Length_Src := Dbms_Lob.Getlength(p_Src);
LOOP
IF i_Pos + c_Max - 1 <= n_Length_Src THEN
n_Amount := c_Max;
ELSE
n_Amount := n_Length_Src - i_Pos + 1;
END IF;
a_Part := Utl_Encode.Base64_Decode(Dbms_Lob.Substr(p_Src, n_Amount, i_Pos));
n_Amount_w := Utl_raw.Length(a_Part);
Dbms_lob.Write(p_Dst, n_Amount_w, i_Pos_w, a_Part);
i_Pos_w := n_Amount_w + i_Pos_w;
i_Pos := n_Amount + i_Pos;
EXIT WHEN i_Pos >= n_Length_Src;
END LOOP;
END IF;
END;


PROCEDURE Parse_Blob(p_Blob IN BLOB
,t_Raw_Tab IN OUT NOCOPY Raw_Table) IS
c_Cr CONSTANT RAW(2) := Utl_Raw.Cast_To_Raw(Chr(13)||chr(10));
i_Blob_Length INTEGER;
Part_Blob RAW(100);
i PLS_INTEGER := 1;
Pos_CR PLS_INTEGER := 1;
BEGIN
t_Raw_Tab.DELETE();
IF p_Blob IS NOT NULL THEN
i_Blob_Length := dbms_lob.GetLength(p_Blob);
LOOP
Pos_CR := dbms_lob.instr(p_Blob, c_Cr, i);
IF Pos_CR != 0 THEN
Part_Blob := dbms_lob.substr(p_Blob,Pos_CR-i,i);
i := Pos_CR + 2;
ELSE
Part_Blob := dbms_lob.substr(p_Blob,i_Blob_Length-i,i);
i := i_Blob_Length;
END IF;
t_Raw_Tab(t_Raw_Tab.Count()+1) := Part_Blob;
EXIT WHEN i >= i_Blob_Length;
END LOOP;
END IF;
END;
{/src}
10 сен 10, 18:26    [9421496]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
stalker_cop
Member

Откуда:
Сообщений: 92
 PROCEDURE Encode_Base64(p_Src IN OUT NOCOPY BLOB
                        ,p_Dst IN OUT NOCOPY BLOB) IS
 c_Max_Length_Base64  CONSTANT PLS_INTEGER := 22848;
/*  
 c_Max_Length_Base64 НЕ МЕНЯТЬ 
 Она подобранна специальным образом
 Исходя из следующих соображений
 32767 - максимальный размер буфера что оракл может сконвертить (на выходе)
 поэтому на входе необходимо подать 32767*0.7 = 22936 байт
 (особенности base64 (три байта конвертятся в четыре))
 Другой особенностью является то что сконвертированный текст режится на строки по 64 символа 
 Так как алгоритм построен просто на склейке выходных данных (после кодирования)
 то необходимо основные данные резать так чтоб длинна была кратна 3 чтоб в конце не было 
 символов "="
 Но и этого не достаточно когда обрабатываются куски входного потока то 
 размер обрабобтанного куска должен быть кратен 64 
 поэтому получаем следующее 64*3*n < 22936 
 путем не сложных вычислений получаем что n = 119
 64*3*119 = 22848 
 вот так получена эта цифра
 можно былобы по другому (вырезать переводы корретки а потом резать по 64 и добавлять
 переводу коретки по моему это лишнее)
*/
 i_Pos                INTEGER := 1;
 n_Amount             BINARY_INTEGER := c_Max_Length_Base64;
 i_Pos_w              INTEGER := 1;
 n_Amount_w           BINARY_INTEGER;
 a_Raw                RAW(32767);
 n_Length_Src         INTEGER;
BEGIN
 IF p_Src IS NOT NULL
    AND Dbms_Lob.Getlength(p_Src) != 0 THEN
  Dbms_lob.Createtemporary(p_Dst,FALSE);
  n_Length_Src := Dbms_Lob.Getlength(p_Src);
  LOOP
   IF i_Pos + c_Max_Length_Base64 - 1 <= n_Length_Src THEN
     n_Amount := c_Max_Length_Base64;
    ELSE
     n_Amount := n_Length_Src - i_Pos + 1;
   END IF;
   a_Raw := Utl_Encode.Base64_Encode(Dbms_Lob.Substr(p_Src, n_Amount, i_Pos));
   n_Amount_w := Utl_Raw.Length(a_Raw);
   Dbms_lob.Write(p_Dst, n_Amount_w, i_Pos_w, a_Raw);
   i_Pos_w := n_Amount_w + i_Pos_w;
   i_Pos := n_Amount + i_Pos;
   EXIT WHEN i_Pos >= n_Length_Src;
  END LOOP;
 END IF;
END;

PROCEDURE Decode_Base64(p_Src IN OUT NOCOPY BLOB
                       ,p_Dst IN OUT NOCOPY BLOB) IS
 c_Max                CONSTANT PLS_INTEGER := 32736;
/*  
 c_Max НЕ МЕНЯТЬ 
 Она подобранна специальным образом
 Исходя из следующих соображений
 32767 - максимальный размер буфера что оракл может сконвертить (на входе)
 на выходе получится примерно 32767*0.7 = 22936 байт
 (особенности base64 (три байта конвертятся в четыре))
 Другой особенностью является то что сконвертированный текст режится на строки по 64 символа 
 Так как алгоритм построен просто на склейке выходных данных (после декодирования)
 то необходимо основные данные резать так чтоб длинна была кратна 4 
 Но и этого не достаточно когда обрабатываются куски входного потока 
 они порезаны по строчкам длинной 66 символов (64 основных и 2 символа перевода корректки 13+10) 
 поэтому получаем следующее 66*4*n < 32767 
 путем не сложных вычислений получаем что n = 119
 66*4*124 = 32736 
 вот так получена эта цифра
*/

 a_Part               RAW(32764);
 i_Pos                INTEGER := 1;
 n_Amount             BINARY_INTEGER := c_Max;
 i_Pos_w              INTEGER := 1;
 n_Amount_w           BINARY_INTEGER;
 n_Length_Src         INTEGER;
BEGIN
 IF p_Src IS NOT NULL
    AND Dbms_Lob.Getlength(p_Src) != 0 THEN
  Dbms_lob.Createtemporary(p_Dst,FALSE);
  n_Length_Src := Dbms_Lob.Getlength(p_Src);
  LOOP
   IF i_Pos + c_Max - 1 <= n_Length_Src THEN
     n_Amount := c_Max;
    ELSE
     n_Amount := n_Length_Src - i_Pos + 1;
   END IF;
   a_Part := Utl_Encode.Base64_Decode(Dbms_Lob.Substr(p_Src, n_Amount, i_Pos));
   n_Amount_w := Utl_raw.Length(a_Part);
   Dbms_lob.Write(p_Dst, n_Amount_w, i_Pos_w, a_Part);
   i_Pos_w := n_Amount_w + i_Pos_w;
   i_Pos := n_Amount + i_Pos;
   EXIT WHEN i_Pos >= n_Length_Src;
  END LOOP;
 END IF;
END;


 PROCEDURE Parse_Blob(p_Blob IN BLOB
                     ,t_Raw_Tab IN OUT NOCOPY Raw_Table) IS
  c_Cr          CONSTANT RAW(2) := Utl_Raw.Cast_To_Raw(Chr(13)||chr(10));
  i_Blob_Length INTEGER;
  Part_Blob     RAW(100);
  i             PLS_INTEGER := 1;
  Pos_CR        PLS_INTEGER := 1;
  BEGIN
   t_Raw_Tab.DELETE();
   IF p_Blob IS NOT NULL THEN
    i_Blob_Length := dbms_lob.GetLength(p_Blob);
    LOOP
     Pos_CR := dbms_lob.instr(p_Blob, c_Cr, i);
     IF Pos_CR != 0 THEN
       Part_Blob := dbms_lob.substr(p_Blob,Pos_CR-i,i);
       i := Pos_CR + 2;
      ELSE
       Part_Blob := dbms_lob.substr(p_Blob,i_Blob_Length-i,i);
       i := i_Blob_Length;
     END IF;
     t_Raw_Tab(t_Raw_Tab.Count()+1) := Part_Blob;
     EXIT WHEN i >= i_Blob_Length;
    END LOOP;
   END IF;
 END;
10 сен 10, 18:29    [9421509]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
Glum1111
автору огромное спасибо!
давно хотел разобраться с этой темой, но как всегда руки не доходили.
доработал для blob и пошагового заполнения текста сообщения, работает действительно безотказно!


Спасибо. А Вы могли бы выложить код, который получился?

Glum1111

но появился такой вопрос:
возможно ли отправлять сообщения на виндусовый msn messenger ?
ситуация такая что не на всех компах настроен outlook express, а необходимость оповещения не уменьшилась.

буду благодарен любой полезной информации


Если протокол открытый, то можно, хотя с почтой мне кажется здесь мало общего. Можно также уведомления слать в icq, тут только проблема в том, что вроде никто еще не делал заготовок для работы с протоколом оскар на оракле, но вот на пхп очень много поделок, например http://wip.asminog.com, поэтому у кого есть силы и желание, можете переложить код на оракл, было бы клево.
19 сен 10, 20:21    [9463644]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
stalker_cop
Всем привет!
Если кому интересно могу отписать как отправить вложение больше чем 32К!
Прикол заключается в том что необходимо закодировать в base64 blob

Спасибо за код. А Вы могли бы привести пример работы с Вашим кодом? Я так понял изначальный блоб должен храниться в бд? Как вариант в таком случае можно блоб сохранить во временный файл, тогда пакет его скушает без особых проблем.
19 сен 10, 20:24    [9463651]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
Предлагающий
Guest
Автору для размышлений.
Бинарники и архивы содержат специфичные символы (например, с кодом 0).
Естественно, данный пакет работать с ними не будут.
20 сен 10, 03:56    [9464358]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
Предлагающий
Автору для размышлений.
Бинарники и архивы содержат специфичные символы (например, с кодом 0).
Естественно, данный пакет работать с ними не будут.

Прикрепляемые файлы переводятся в base64, в чем проблема то? Все работает, бинарники и архивы отправляются без проблем.
20 сен 10, 08:22    [9464459]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
stalker_cop
Member

Откуда:
Сообщений: 92
chameleon82
stalker_cop
Всем привет!
Если кому интересно могу отписать как отправить вложение больше чем 32К!
Прикол заключается в том что необходимо закодировать в base64 blob

Спасибо за код. А Вы могли бы привести пример работы с Вашим кодом? Я так понял изначальный блоб должен храниться в бд? Как вариант в таком случае можно блоб сохранить во временный файл, тогда пакет его скушает без особых проблем.


Всем привет
Я просто предоставил три процедурки которые кодируют и раскодируют блоб в/из base64. В последнем варианте отправки писем отредактировать вызов utl_smtp.write_raw_data(v_Mail_Conn, UTL_ENCODE.base64_encode(vRAW)); На то что я представил (но не в лоб там начитка из файла для начала файл в blob а потом нарезать на кусочки и отправить)
23 сен 10, 09:57    [9486683]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
iceFR
Member

Откуда:
Сообщений: 40
Всем привет.

Скажите, а как обстоят дела с отправкой в русской кодировке? пробовал варианты типа:
 'content-type: text/plain; charset="koi8-r"'
и прочие варианты кодировок, но ничего из этого путного не вышло.
28 сен 10, 11:29    [9512819]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
Basil A. Sidorov
Member

Откуда:
Сообщений: 7273
iceFR
пробовал варианты типа:
 'content-type: text/plain; charset="koi8-r"'
и прочие варианты кодировок, но ничего из этого путного не вышло.
А то, что вы отправляете действительно в koi8-r или вы наивно полагаете, что "кто-то" перекодирует отправляемое из неизвестно чего в то, что нужно?
28 сен 10, 15:39    [9515882]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
longman
Member

Откуда:
Сообщений: 33
Друзья! пытаюсь воспользоваться предложенным "готовым решением".
Сервер БД: Solaris
СУБД: Oracle 9ir2
Цель: отправлять почту c вложениями (txt, pdf, xls, doc), взятыми из таблицы БД (blob).
При этом сначала вычитываю необходимые файлы в каталог на файловой системе сервера БД. Для этого дописал пакет процедурой (код взят из инета.. неоднократно фигурирует, одно что изменил режим работы utl_file.fopen с WB на W):

-------------------------------------------------------------------------------------------------------
-- Extract_File
-------------------------------------------------------------------------------------------------------
PROCEDURE Extract_File (l_table in varchar2, 
  				l_pkey_field in varchar2, 
                                l_blob_field in varchar2, 
                                l_pkey_value in varchar2,
				l_dir in varchar2,                        
				l_filename in varchar2) IS
    vblob BLOB;
    vstart NUMBER := 1;
    bytelen NUMBER := 32000;
    len NUMBER:=0;
    my_vr RAW(32000);
    x NUMBER;

    query_string varchar2(500)  :='select '||l_blob_field||
                                  ' from '||l_table||
                                  ' where '||l_pkey_field||
                                  ' = '''||l_pkey_value||'''';

    l_output utl_file.file_type;
BEGIN
    -- define output directory
    l_output := utl_file.fopen(l_dir, l_filename, 'W', 32760);

    vstart := 1;
    bytelen := 32000;

    -- get length of blob
    len := lob_client_operations.get_lob_size(l_table, l_pkey_field, l_blob_field, to_char(l_pkey_value));

    -- save blob length
    x := len;
    
    -- select blob into variable
    execute immediate query_string into vblob;
      
    -- if small enough for a single write
    IF len < 32760 THEN
		    utl_file.put_raw(l_output,vblob);
    		utl_file.fflush(l_output);
    ELSE -- write in pieces
		    vstart := 1;

        WHILE vstart < len and bytelen > 0
        LOOP
            dbms_lob.read(vblob,bytelen,vstart,my_vr);

            utl_file.put_raw(l_output,my_vr);
            utl_file.fflush(l_output);

            -- set the start position for the next cut
            vstart := vstart + bytelen;

            -- set the end position if less than 32000 bytes
            x := x - bytelen;
            IF x < 32000 THEN
	              bytelen := x;
            END IF;
        end loop;
    END IF;

    utl_file.fclose(l_output);
    
exception
  	when others then
      	raise_application_error(-20501, 'Procedure MAIL_PKG.Extract_File: '||sqlerrm);
end;

всё работает (отсылаются и большие файлы.. пробовал вложений на ~5 мб), но ровным счётом до момента пока не попадётся хитрый файл, который изначально полностью не вычитывается из БД и стопорится на одном и том же месте с ошибкой ORA-29285 - Ошибка записи в файл.. поиском по гуглу обнаружил, что это некий bug 2883782 on MetaLink. внимание, вопрос: кто либо сталкивался с подобным и есть ли решение данной проблемы? Спасибо!

вот одна из ссылок на эту тему c указанием сути проблемы http://www.idevelopment.info/data/Oracle/DBA_tips/LOBs/LOBS_10.shtml
5 окт 10, 12:43    [9554064]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
-2-
Member

Откуда:
Сообщений: 12953
longman,

Возможно utl_file пользуется функциями stdio с контролем utf8. Не все комбинации допустимы при записи текстовыми функциями. На 11g utl_file.fopen имеет параметр open_mode => 'wb'.
5 окт 10, 12:57    [9554225]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
env
Member

Откуда: Россия, Москва
Сообщений: 5253
longman,

Ты не поверишь....

Но это именно из-за твоей замены
longman
режим работы utl_file.fopen с WB на W


В некоторых случаях, последовательность строк, записываемых в текстовый файл при использовании обычного вызова

 f  utl_file.file_type;
 ...
 f := utl_file.fopen('SOME_DATA_DIR',fname,'W');
 ...
 utl_file.put_line(f,fdata);
 ...
 utl_file.fclose(f);

под Linux/*nix вызывает ошибку записи в файл (получается "неправильная" для utf-8 последовательность символов) и процедура завершается с ошибкой
ORA-29285: file write error

Чтобы избежать этой ошибки, запись следует производить в файл, открываемый как двоичный, и в коде формировать окончания строк
 f  utl_file.file_type;
 line_end char(2) := chr(13)||chr(10); --ежели отдаём под винду
 ...
 f := utl_file.fopen('SOME_DATA_DIR',fname,'WB');
 ...
 utl_file.put_raw(f, utl_raw.cast_to_raw(r.fdata || line_end));
5 окт 10, 13:09    [9554339]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
longman
Member

Откуда:
Сообщений: 33
-2-,
Bug : UTL_FILE.PUT_RAW RESULTS IN ORA-29285 DUMPING LARGE AMOUNT OF TABLE DATA

почитал на металинке.. баг тебе и всё.. если добавить команду utl_file.new_line(f_descr) после utl_file.fflush(f_descr), то ошибки нет, но естественно файлы битыми приходят. ну и в итоге как отправить почту с вложениями, чтоб эта процедура могла запускаться через Job? кто подскажет?
5 окт 10, 13:11    [9554353]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
env
Member

Откуда: Россия, Москва
Сообщений: 5253
Возможно лучше будет просто не заморачиваться с файлами, и формировать вложения напрямую из блобов.
5 окт 10, 13:14    [9554380]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
longman
Member

Откуда:
Сообщений: 33
env,
а несколько подробнее?
5 окт 10, 13:28    [9554562]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
env
Member

Откуда: Россия, Москва
Сообщений: 5253
longman,

пожалуйста
5 окт 10, 14:12    [9555109]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
-2-
Member

Откуда:
Сообщений: 12953
longman,

Попробуй перезапустить инстанс с неустановленными переменными окружения LC_xxx и LANG=en_US.iso885915 (или что-то еще 8-битное).

Запись лоба без выкладки в файловую систему - первый пост, просто вместо dbms_lob.fileopen(bfile) -> dbms_lob.open(blob)
5 окт 10, 14:14    [9555134]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
stalker_cop
Member

Откуда:
Сообщений: 92
А зачем тебе вообще BLOB записывать на файловую систему?
В данном случаи тебе нужно BLOB просто перекодировать в base64
в данном топике есть все необходимое чтоб переделать "готовое решение" под себя.
5 окт 10, 15:15    [9555812]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
longman
Member

Откуда:
Сообщений: 33
-2-, ничего перезапустить не могу, т.к. БД производственная и мной не управляется)
stalker_cop, переписал код первого поста, а точнее добавил получение Blob на уровне процедуры Send. Всё получилось как нельзя лучше! сейчас опробую пакетные вложения.. на одном файле всё отправилось и доставилось! Спасибо за мысль! Кстати и env так же высказываю благодарность..
5 окт 10, 15:37    [9556050]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
longman
Member

Откуда:
Сообщений: 33
и снова здравствуйте! ситуация такова) всё отправляется, практически все требования реализованы.. но при получении письмо содержит порцию кракозябров.. по одной на каждый вложенный файл.. причём на некоторых веб-почтовиках они отображаются, на некоторых нет.. в The Bat! также присутствуют.. (оттуда скриншот не делал.. если нужно - сделаю) во вложении к посту скриншот с почты Mail.ru и Gmail.com.. кто в курсе природы этих символов?
8 окт 10, 09:37    [9573287]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
longman
Member

Откуда:
Сообщений: 33
файл не вложился в предыд. посте..

К сообщению приложен файл. Размер - 0Kb
8 окт 10, 09:39    [9573296]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
longman
Member

Откуда:
Сообщений: 33
вот скрин с The Bat! на вкладке с файлом doc до 10 символов-кракозябров

К сообщению приложен файл. Размер - 0Kb
8 окт 10, 10:18    [9573547]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
Basil A. Sidorov
Member

Откуда:
Сообщений: 7273
longman
вот скрин с The Bat! на вкладке с файлом doc до 10 символов-кракозябров
PDF это такой "почти текст" и на ваших скриншотах это хорошо видно.
В чём проблема-то?
8 окт 10, 15:30    [9576826]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
longman
Member

Откуда:
Сообщений: 33
отвечаю сам себе) чтоб подобных лишних вещиц не было, надо в поле Content-Type при формировании письма, а точнее секции вложений необходимо указать не стандартный text/plain (text/html), а что-то типа APPLICATION/MSWORD для doc-ов, APPLICATION/PDF для pdf-ов.. вот как бы и всё решение.. также реализовал использование HTML-файла вместо текстового body письма (понятно, что можно просто в body передать теги, но конечный пользователь такими знаниями увы не владеет).. в целом ничего сложного, кому нужно спрашивайте.. всем спасибо..
8 окт 10, 15:53    [9576982]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
Basil A. Sidorov
Member

Откуда:
Сообщений: 7273
longman
отвечаю сам себе) чтоб подобных лишних вещиц не было, надо в поле Content-Type
Надо "щитильнее" курить первоисточники. RFC2045-RFC2049 - в данном случае.
8 окт 10, 20:11    [9578531]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
Всем спасибо за подсказки.
Я в свою очередь обновил пакет, добавил возможность вставлять блобы (из базы или сформированные вручную).
Выкладываю обновленную версию целиком:
CREATE OR REPLACE PACKAGE MAIL_PKG IS
-- --------------------------------------------------------------------------
-- Name         : MAIL_PKG
-- Author       : Nekrasov Alexander
-- Description  : Mail package, send email with attachments
-- Ammedments   :
--   When         Who         What
--   ===========  ==========  =================================================
--   22-JAN-2010  Nekrasov A.  Initial Creation
--   26-MAY-2010  Nekrasov A.  Update package bugs
--   11-OCT-2010  Nekrasov A.  Add Blob attachments
-- --------------------------------------------------------------------------

/* EXAMPLE:

 1) Short text email

    BEGIN
      MAIL_PKG.SEND( 'a.ivanov@yourcomany.ru','Test subject', 'Some message!');
	END;

 2) Send mail with message over 32kbytes
    DECLARE
      vBlob BLOB;
  	BEGIN
	 SELECT file_data INTO vBlob FROM FND_LOBS WHERE FILE_ID = 161005;						
	 MAIL_PKG.ADD_ATTACHMENT( vBlob
							 ,'MessageOver32kb.htm'
							 ,'text/html'
							);							
      MAIL_PKG.SEND( 'a.ivanov@yourcomany.ru','Big message', NULL);	
	END;
	
 3) Extension Email with attacments
    DECLARE
      vBlob BLOB;
    BEGIN
	 MAIL_PKG.SET_MAILSERVER ('localhost',25);
	 MAIL_PKG.SET_AUTH ('a.nekrasov','password');

	 -- Add attachment from file 
	 MAIL_PKG.ADD_ATTACHMENT( 'ODPDIR'
							 ,'girl3d.jpeg'
							 ,'image/jpeg'
							);

	 -- Add attachment from BLOB	
	 SELECT file_data INTO vBlob FROM FND_LOBS WHERE FILE_ID = 161005;						
	 MAIL_PKG.ADD_ATTACHMENT( vBlob
							 ,'ReportResult.htm'
							 ,'text/html'
							);							

	 MAIL_PKG.SEND( mailto => 'A. Ivanov <a.ivanov@yourcomany.ru>, O.Petrov <o.petrov@yourcompany.ru>'
	              , subject => 'Test subject'
				  , message => 'Some <b>bold</b> message!'
				  , mailfrom => 'Oracle Notify <no-reply@yourcompany.ru>'
                  , mimetype => 'text/html'
				  , priority => 1
	              );
	END;
*/

 -- SET_MAILSERVER:
 --  Set up mail server for send emails. Default Localhost
 -- IN
 -- MAILSERVER is ip or url of mail server
 -- MAILPORT is port for mail server. Default 25
 PROCEDURE SET_MAILSERVER ( mailserver varchar2
                          , mailport number default 25
                          );

 -- SET_AUTH
 --  Set authorization on smtp server
 -- IN
 -- AUTH_USER is authorization user
 -- AUTH_PASS is password for AUTH_USER
 --
 -- Execute SET_AUTH(); -- for disable authorization
 PROCEDURE SET_AUTH (  auth_user varchar2 default null
                     , auth_pass varchar2 default null
                          );

 -- ENCODE:
 --  Encodes string to email compatible view
 -- IN
 -- STR is string to convert
 -- TP is type of convert:
 --    B - is base64 encoding
 FUNCTION ENCODE( str IN VARCHAR2
                , tp IN VARCHAR2 DEFAULT 'Q') RETURN VARCHAR2;

 -- PREPARE
 --  Prepare configs for email.
 PROCEDURE PREPARE;

 -- ADD_RCPT
 --  Add recipient to recipients list exploded by  ','
 -- STR is variable with recipients
 -- RCPTMAIL is recipient mail added to STR
 -- RCPTNAME is recipient name added to STR
 -- Example: str='user1@domain.ru' rcptmail='user2@domain.ru'
 --  after => str='user1@domain.ru, user2@domain.ru'
 PROCEDURE ADD_RCPT( str IN OUT VARCHAR2
                   , rcptmail IN VARCHAR2
				   , rcptname IN VARCHAR2 DEFAULT NULL);

 -- ADD_ATTACHMENT
 --  Add file-attachment to attachments list to email
 -- IN
 -- DIRNAME is logical link to access physical directories of server. See DBA_DIRECTORIES table
 -- FILENAME is name of file to attach
 -- MIMETYPE is mime-type for sended file
 -- NAME is name for attached file for email. Default eq FILENAME
 PROCEDURE ADD_ATTACHMENT ( dirname IN varchar2
                          , filename IN varchar2
						  , mimetype IN varchar2 DEFAULT 'text/plain'
                          , name IN varchar2 DEFAULT NULL
                           );
 -- ADD_ATTACHMENT
 --  Add blob-attachment to attachments list to email
 -- IN
 -- BLOBLOC - Blob locator for attached blob
 -- FILENAME is name of file to attach
 -- MIMETYPE is mime-type for sended file
 PROCEDURE ADD_ATTACHMENT ( blobloc IN blob
                          , filename IN varchar2
						  , mimetype IN varchar2 DEFAULT 'text/html'
                           );
						   
 -- SEND
 --  Send email with attachments to recipient
 -- IN
 -- MAILTO is name and email addresses of recipients ( ex. "user@domain.com"
 --       , "User Name <user@domain.com>", "User1 <user1@domain>, User2 <user2@domain>")
 -- SUBJECT is subject of email
 -- MESSAGE is message of email
 -- MAILFROM is name and email of sender. (ex. "no-reply@domain", "Notify system <no-reply@domain>")
 -- MIMETYPE is mime-type of message. Available values is 'text/plain' and 'text/html'
 -- PRIORITY is priority of mail (1 - High, 2 - Highest, 3 - Normal, 4 - Lowest, 5 - Low)
 PROCEDURE SEND ( mailto IN VARCHAR2
				, subject IN VARCHAR2
				, message IN VARCHAR2
                , mailfrom IN VARCHAR2 DEFAULT NULL
				, mimetype IN VARCHAR2 DEFAULT 'text/plain'
				, priority IN NUMBER DEFAULT NULL
                );
END MAIL_PKG;
/

CREATE OR REPLACE PACKAGE BODY MAIL_PKG
IS

 mailserver VARCHAR2(30):='localhost';
 mailport INTEGER:=25;
 auth_user VARCHAR2(50);
 auth_pass VARCHAR2(50);
 crlf         VARCHAR2(2)  := utl_tcp.CRLF; -- chr(13)||chr(10);

 type attach_row is record ( dirname varchar2(30)
                           , filename  varchar2(30)
                           , name  varchar2(30)
						   , mimetype varchar2(30)
						   , blobloc blob
						   , attachtype varchar2(30)
                           );
 type attach_list is table of attach_row;
 attachments attach_list;

 type rcpt_row is record ( rcptname varchar2(100)
                     , rcptmail varchar2(50)
					 );
 type rcpt_list is table of rcpt_row;

 PROCEDURE SET_MAILSERVER ( mailserver varchar2
                          , mailport number default 25
                          ) IS
 BEGIN
  MAIL_PKG.mailserver := mailserver;
  MAIL_PKG.mailport := mailport;
 END;

 PROCEDURE SET_AUTH (  auth_user varchar2 default null
                     , auth_pass varchar2 default null
                          ) IS
 BEGIN
   MAIL_PKG.auth_user := auth_user;
   MAIL_PKG.auth_pass := auth_pass;
 END;

 FUNCTION ENCODE(str IN VARCHAR2, tp IN VARCHAR2 DEFAULT 'Q') RETURN VARCHAR2 IS
 BEGIN
   IF tp='B' THEN
     RETURN '=?utf-8?b?'|| UTL_RAW.cast_to_varchar2(UTL_ENCODE.base64_encode(UTL_RAW.cast_to_raw (CONVERT (SUBSTR(str,1,24), 'UTF8'))))|| '?='
	     || CASE WHEN SUBSTR(str,25) IS NOT NULL THEN crlf || ' '|| ENCODE(SUBSTR(str,25),tp) END;
   ELSIF tp='Q' THEN
     RETURN '=?utf-8?q?' || UTL_RAW.cast_to_varchar2(utl_encode.QUOTED_PRINTABLE_ENCODE(utl_raw.cast_to_raw(CONVERT (SUBSTR(str,1,8), 'UTF8') ))) || '?='
	     || CASE WHEN SUBSTR(str,9) IS NOT NULL THEN crlf || ' '|| ENCODE(SUBSTR(str,9),tp) END;
   ELSE
     RETURN str;
   END IF;
 END;

 PROCEDURE PREPARE
 IS
 BEGIN
   MAIL_PKG.attachments:=MAIL_PKG.attach_list();
 END;

 PROCEDURE ADD_RCPT( str IN OUT VARCHAR2
                   , rcptmail IN VARCHAR2
				   , rcptname IN VARCHAR2 DEFAULT NULL) IS
  rcpt varchar2(255);
 BEGIN
  rcpt:=CASE WHEN rcptname is null THEN
          rcptmail
		ELSE
		  trim(replace(replace(rcptname,',',' '),';',' '))||' <'|| rcptmail ||'>'
		END;
  IF trim(str) is NULL THEN
     str :=  trim(rcpt);
  ELSE
     str := str||', '||trim(rcpt);
  END IF;
 END;

 PROCEDURE ADD_ATTACHMENT ( dirname IN varchar2
                          , filename IN varchar2
						  , mimetype IN varchar2 DEFAULT 'text/plain'
                          , name IN varchar2 DEFAULT NULL
                           )
 IS
  v_fl BFILE :=BFILENAME(dirname,filename);
 BEGIN
   IF DBMS_LOB.FILEEXISTS (v_fl)=1 THEN
      MAIL_PKG.attachments.extend;
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).dirname:=dirname;
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).filename:=filename;
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).name:=nvl(name,filename);
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).mimetype:=mimetype;
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).attachtype:='FILE';	  
   ELSE
      RAISE_APPLICATION_ERROR(-20001, 'File is not exists');
   END IF;
 END;
 
 PROCEDURE ADD_ATTACHMENT ( blobloc IN blob
                          , filename IN varchar2
						  , mimetype IN varchar2 DEFAULT 'text/html'
                           )
 IS 
 BEGIN
      MAIL_PKG.attachments.extend;
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).name:=filename;
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).mimetype:=mimetype;
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).blobloc:=blobloc;	  
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).attachtype:='BLOB';	  
 END; 						   
 

 FUNCTION CREATE_RCPT_LIST(mailto IN VARCHAR2) RETURN MAIL_PKG.rcpt_list IS
  v_mailto VARCHAR2(4096) := replace(mailto,';',',')||',';
  pntr INTEGER;
  buf VARCHAR2(255);
  rcptmail VARCHAR2(255);
  rcptlist MAIL_PKG.rcpt_list:=MAIL_PKG.rcpt_list();
 BEGIN
  FOR maxrcptnts IN 1..50
  LOOP
     pntr:=INSTR(v_mailto,','); buf := substr(v_mailto,1,pntr-1);
     IF pntr>0 THEN
	   IF INSTR(buf,'<')>0 AND INSTR(buf,'>')>0 THEN
	     rcptmail:= SUBSTR(buf,INSTR(buf,'<')+1,INSTR(SUBSTR(buf,INSTR(buf,'<')+1),'>')-1);
		 IF rcptmail IS NOT NULL THEN
	        rcptlist.extend;
		    rcptlist(rcptlist.count).rcptmail := TRIM(rcptmail);
		    rcptlist(rcptlist.count).rcptname := TRIM(SUBSTR(buf,1,INSTR(buf,'<')-1));
	     END IF;
       ELSE
	     rcptmail := TRIM(buf);
		 IF rcptmail IS NOT NULL THEN
           rcptlist.extend;
		   rcptlist(rcptlist.count).rcptmail:= TRIM(rcptmail);
		 END IF;
	   END IF;
	 ELSE
	   EXIT;
	 END IF;
	 v_mailto := substr(v_mailto,pntr+1);
   END LOOP;
   RETURN rcptlist;
 END;

 PROCEDURE SEND ( mailto IN VARCHAR2
				, subject IN VARCHAR2
				, message IN VARCHAR2
                , mailfrom IN VARCHAR2 DEFAULT NULL
				, mimetype IN VARCHAR2 DEFAULT 'text/plain'
				, priority IN NUMBER DEFAULT NULL
                )
 IS
   v_Mail_Conn  utl_smtp.Connection;
   boundary VARCHAR2(50) := '-----7D81B75CCC90DFRW4F7A1CBD';
   vFile BFILE;
   vRAW RAW(32767);
   amt CONSTANT BINARY_INTEGER := 48; -- 48bytes binary convert to 128bytes of base64.
   v_amt BINARY_INTEGER;
   ps BINARY_INTEGER := 1;
   v_mime VARCHAR2(30);
   reply UTL_SMTP.REPLY;
   replies UTL_SMTP.REPLIES;
   rcptlist MAIL_PKG.rcpt_list;
   sndr MAIL_PKG.rcpt_row;
 BEGIN
    rcptlist:=create_rcpt_list(mailto);
	IF rcptlist.count=0 THEN
      RAISE_APPLICATION_ERROR(-20001, 'Recipients requered');
	END IF;
    IF mimetype<>'text/html' and mimetype<>'text/plain' THEN
      RAISE_APPLICATION_ERROR(-20001, 'MimeType must be "text/html" or "text/plain"');
    ELSE
      v_mime:=mimetype;
    END IF;
    v_Mail_Conn := utl_smtp.Open_Connection(MAIL_PKG.mailserver, MAIL_PKG.mailport);
    replies:=utl_smtp.Ehlo(v_Mail_Conn,MAIL_PKG.mailserver);
	if create_rcpt_list(mailfrom).count>0 then
	  sndr := create_rcpt_list(mailfrom)(1);
	else
	  sndr := create_rcpt_list( 'mail@' || UTL_INADDR.GET_HOST_NAME )(1); -- host from oracle-server
	  -- sndr := create_rcpt_list( 'mail@' || substr(replies(1).text,1,instr(replies(1).text,' ')-1))(1); -- Addr from ehlo answer
    end if;

    if mail_pkg.auth_user is not null then
       for x IN 1 .. replies.count loop
 	     IF INSTR(replies(x).text,'AUTH')>0 then -- If server supply authorization
            utl_smtp.command(v_Mail_Conn, 'AUTH LOGIN');
            utl_smtp.command(v_Mail_Conn,utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(auth_user))));
            utl_smtp.command(v_Mail_Conn,utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(auth_pass))));
			exit;
		 END IF;
	   end loop;
    end if;

    utl_smtp.Mail(v_Mail_Conn, sndr.rcptmail);
    FOR rcpts IN 1 .. rcptlist.count
	LOOP
	  utl_smtp.Rcpt(v_Mail_Conn, rcptlist(rcpts).rcptmail);
	END LOOP;

    utl_smtp.open_data(v_Mail_Conn); -- open data sheet

	utl_smtp.write_data(v_Mail_Conn, 'Date: ' || to_char(sysdate, 'Dy, DD Mon YYYY hh24:mi:ss','NLS_DATE_LANGUAGE = ''american''') || crlf);
    utl_smtp.write_data(v_Mail_Conn, 'From: ');
	if sndr.rcptname is not null then
        utl_smtp.write_data(v_Mail_Conn, MAIL_PKG.ENCODE(sndr.rcptname) ||' <'|| sndr.rcptmail || '>');
	else
        utl_smtp.write_data(v_Mail_Conn, sndr.rcptmail);
	end if;
    utl_smtp.write_data(v_Mail_Conn, crlf );
    utl_smtp.write_data(v_Mail_Conn, 'Subject: '|| MAIL_PKG.ENCODE(subject) || crlf );
    utl_smtp.write_data(v_Mail_Conn, 'To: ');
    FOR rcpts IN 1 .. rcptlist.count
	LOOP
	  if rcpts>1 then
       utl_smtp.write_data(v_Mail_Conn, ',');
	  end if;
	  if rcptlist(rcpts).rcptname is not null then
        utl_smtp.write_data(v_Mail_Conn, MAIL_PKG.ENCODE(rcptlist(rcpts).rcptname) ||' <'|| rcptlist(rcpts).rcptmail || '>');
	  else
        utl_smtp.write_data(v_Mail_Conn, rcptlist(rcpts).rcptmail);
	  end if;
	END LOOP;
    utl_smtp.write_data(v_Mail_Conn, crlf );

	IF priority IS NOT NULL and priority BETWEEN 1 AND 5 THEN
      utl_smtp.write_data(v_Mail_Conn, 'X-Priority: ' || priority || crlf );
	END IF;
    utl_smtp.write_data(v_Mail_Conn, 'MIME-version: 1.0' || crlf );
    utl_smtp.write_data(v_Mail_Conn, 'Content-Type: multipart/mixed;'|| crlf );
    utl_smtp.write_data(v_Mail_Conn, ' boundary="'||boundary||'"'|| crlf );
    utl_smtp.write_data(v_Mail_Conn, crlf );
 
    --Message
	IF message IS NOT NULL THEN	
    utl_smtp.write_data(v_Mail_Conn, '--'|| boundary || crlf );
    utl_smtp.write_data(v_Mail_Conn, 'Content-Type: '||v_mime||'; charset="utf-8"'|| crlf );
    utl_smtp.write_data(v_Mail_Conn, 'Content-Transfer-Encoding: 8bit'|| crlf );
    utl_smtp.write_data(v_Mail_Conn, crlf );
    utl_smtp.write_raw_data(v_Mail_Conn, utl_raw.cast_to_raw(CONVERT(message,'UTF8')));
    utl_smtp.write_data(v_Mail_Conn, crlf );
    utl_smtp.write_data(v_Mail_Conn, crlf );
    END IF;
	
	--Attachments
	IF MAIL_PKG.attachments.count>0 THEN
	  FOR x IN 1 .. MAIL_PKG.attachments.count LOOP
          utl_smtp.write_data(v_Mail_Conn, '--'|| boundary || crlf );
          utl_smtp.write_data(v_Mail_Conn, 'Content-Type: '||MAIL_PKG.attachments(x).mimetype||';'|| crlf );
          utl_smtp.write_data(v_Mail_Conn, ' name="');
		  utl_smtp.write_raw_data(v_Mail_Conn,utl_raw.cast_to_raw(MAIL_PKG.attachments(x).name));
          utl_smtp.write_data(v_Mail_Conn, '"' || crlf);
          utl_smtp.write_data(v_Mail_Conn, 'Content-Transfer-Encoding: base64'|| crlf );
          utl_smtp.write_data(v_Mail_Conn, 'Content-Disposition: attachment;'|| crlf );
          utl_smtp.write_data(v_Mail_Conn, ' filename="' || MAIL_PKG.ENCODE(MAIL_PKG.attachments(x).name) || '"' || crlf);
          utl_smtp.write_data(v_Mail_Conn, crlf );
		  IF MAIL_PKG.attachments(x).attachtype = 'FILE' THEN 
             vFile := BFILENAME(MAIL_PKG.attachments(x).dirname,MAIL_PKG.attachments(x).filename);
		     dbms_lob.fileopen(vFile, dbms_lob.file_readonly);
             ps:=1; v_amt:=amt;
		     LOOP
		       BEGIN
		         dbms_lob.read (vFile, v_amt, ps, vRAW);
			     ps := ps + v_amt;
                 utl_smtp.write_raw_data(v_Mail_Conn, UTL_ENCODE.base64_encode(vRAW));
		       EXCEPTION
                 WHEN no_data_found THEN
			       EXIT;
			   END;			
		     END LOOP;
		     dbms_lob.fileclose(vFile);
		  ELSIF MAIL_PKG.attachments(x).attachtype = 'BLOB' THEN
		  	 dbms_lob.open(MAIL_PKG.attachments(x).blobloc, dbms_lob.file_readonly);
             ps:=1; v_amt:=amt;
		     LOOP
		       BEGIN
		         dbms_lob.read (MAIL_PKG.attachments(x).blobloc, v_amt, ps, vRAW);
			     ps := ps + v_amt;
                 utl_smtp.write_raw_data(v_Mail_Conn, UTL_ENCODE.base64_encode(vRAW));
		       EXCEPTION
                 WHEN no_data_found THEN
			       EXIT;
			   END;			
		     END LOOP;
		     dbms_lob.close(MAIL_PKG.attachments(x).blobloc);					  	 
		  END IF;		 		  

          utl_smtp.write_data(v_Mail_Conn, crlf );
          utl_smtp.write_data(v_Mail_Conn, crlf );
	  END LOOP;
	END IF;

    -- Final Boundary
    utl_smtp.write_data(v_Mail_Conn, '--' || boundary || '--');

    utl_smtp.close_data(v_Mail_Conn);
    utl_smtp.quit(v_Mail_Conn);

	-- Clear attachments
    MAIL_PKG.attachments:=MAIL_PKG.attach_list();

 EXCEPTION
    WHEN OTHERS THEN
       BEGIN
         MAIL_PKG.attachments:=MAIL_PKG.attach_list();
		 utl_smtp.rset(v_Mail_Conn);
	     utl_smtp.quit(v_Mail_Conn);
	   EXCEPTION WHEN OTHERS THEN NULL;
	   END;
	RAISE;
 END;

BEGIN
  MAIL_PKG.attachments:=MAIL_PKG.attach_list();
END;
/
11 окт 10, 11:42    [9585453]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
uranic
Member

Откуда:
Сообщений: 291
Подскажите в какую сторону копать, чтобы прикрутить pop3 аутентификацию?
13 окт 10, 23:37    [9603859]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
Basil A. Sidorov
Member

Откуда:
Сообщений: 7273
uranic
Подскажите в какую сторону копать, чтобы прикрутить pop3 аутентификацию?
"POP before SMTP", если уж быть точным.
Копать, как я понимаю, в сторону какого-нибудь UTL_TCP. Если, конечно, нет никакого UTL_POP3 :)
13 окт 10, 23:55    [9603937]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
Uncle Tola
Member

Откуда:
Сообщений: 86
Огромное Спасибо за Пакет!

Скажите, как создать письмо с размером более 32К ?
Делаю вот так:


2) Send mail with message over 32kbytes
    DECLARE
      vBlob BLOB;
  	BEGIN
	 SELECT file_data INTO vBlob FROM FND_LOBS WHERE FILE_ID = 161005;						
	 MAIL_PKG.ADD_ATTACHMENT( vBlob
							 ,'MessageOver32kb.htm'
							 ,'text/html'
							);							
      MAIL_PKG.SEND( 'a.ivanov@yourcomany.ru','Big message', NULL);	
	END;


В результате приходит письмо с файлом аттачем MessageOver32kb.htm
Можно ли как то сделать чтобы приходило письмо где в body текст (более 32К), а не письмо с аттачем ?

Вроде выше писали, надо поставить какой то хитрый mimetype ?
26 ноя 10, 16:59    [9846749]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
Охрименко
Member

Откуда: Украина, Киев
Сообщений: 1421
Вот мое решение :) Тоже много искал, гуглил, исправлял под себя. В письме выглядит немного странно, а именно не могу расшифровать как просто перевести строку. оно либо тулит весь текст в одну строку без переносов, либо вставляет пустую строку. Я выбрал вариант с пустой строкой. Больше 32К возможно. Текст без вложений. Это из джоба генерируется если есть джобы у которых BROKEN='Y' или FAILURES>0. Редактируйте по своему усмотрению.

/* Formatted on 26.11.2010 16:07:42 (QP5 v5.163.1008.3004) */
DECLARE
   sender        VARCHAR2 (50) DEFAULT 'oracleinfo@xx.ua';
   recipient1    VARCHAR2 (50) DEFAULT 'dba@xx.ua';
   subject       VARCHAR2 (50) DEFAULT 'Прерванные джобы с ошибкой';
   mailhost      VARCHAR2 (50) DEFAULT '192.168.XX.XX';
   mail_conn     UTL_SMTP.connection;
   crlf CONSTANT VARCHAR2 (2) := CHR (13) || CHR (10);
   smtp_tcpip_port CONSTANT PLS_INTEGER := 25;
   rowcnt        INTEGER := 0;

   PROCEDURE writedata (str IN VARCHAR2)
   IS
   BEGIN
      UTL_SMTP.write_data (mail_conn, str);
   END;
BEGIN
   SELECT COUNT (*)
     INTO rowcnt
     FROM dba_jobs
    WHERE broken = 'Y' OR Failures > 0;

   IF rowcnt > 0
   THEN
      mail_conn := UTL_SMTP.open_connection (mailhost, smtp_tcpip_port);
      UTL_SMTP.helo (mail_conn, mailhost);
      UTL_SMTP.mail (mail_conn, sender);
      UTL_SMTP.rcpt (mail_conn, recipient1);
      UTL_SMTP.open_data (mail_conn);
      writedata (
            'Date: '
         || TO_CHAR (SYSTIMESTAMP, 'Dy, dd Mon YYYY HH24:MI:SS TZHTZM')
         || crlf
         || 'From: '
         || sender
         || crlf
         || 'Content-Type: text/plain; charset=windows-1251'
         || crlf
         || 'MIME-Version: 1.0'
         || crlf
         || 'To: '
         || recipient1
         || crlf
         || 'Content-Transfer-Encoding: 8bit'
         || crlf);
      UTL_SMTP.WRITE_RAW_DATA (mail_conn, UTL_RAW.CAST_TO_RAW ('Subject: ' || subject || UTL_TCP.CRLF));
      UTL_SMTP.WRITE_RAW_DATA (mail_conn, UTL_RAW.CAST_TO_RAW (UTL_TCP.CRLF));

      FOR cur IN (SELECT job,
                         priv_user,
                         last_date,
                         broken,
                         failures
                    FROM dba_jobs
                   WHERE broken = 'Y' OR Failures > 0)
      LOOP
         UTL_SMTP.write_raw_data (
            mail_conn,
            UTL_RAW.cast_to_raw (
                  'Джоб №'
               || cur.job
               || ' User:'
               || TO_CHAR (cur.priv_user)
               || ' Последний раз удачно выполнился:'
               || TO_CHAR (cur.last_date, 'HH24:MI:SS')
               || ' Статус Broken='
               || cur.broken
               || ' Статус Failures='
               || cur.Failures
               || UTL_TCP.crlf
               || CHR (10)));
      END LOOP;

      UTL_SMTP.close_data (mail_conn);
      UTL_SMTP.QUIT (mail_conn);
   END IF;
EXCEPTION
   WHEN OTHERS
   THEN
      UTL_SMTP.RSET (mail_conn);
END;
26 ноя 10, 17:10    [9846821]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
Uncle Tola
Огромное Спасибо за Пакет!

Скажите, как создать письмо с размером более 32К ?
Делаю вот так:

В результате приходит письмо с файлом аттачем MessageOver32kb.htm
Можно ли как то сделать чтобы приходило письмо где в body текст (более 32К), а не письмо с аттачем ?

Вроде выше писали, надо поставить какой то хитрый mimetype ?


Быстрый фикс
Найдите в тексте пакета эти строки (в разделе добавления атачей при отправке письма)
utl_smtp.write_data(v_Mail_Conn, '--'|| boundary || crlf );
          utl_smtp.write_data(v_Mail_Conn, 'Content-Type: '||MAIL_PKG.attachments(x).mimetype||';'|| crlf );
          utl_smtp.write_data(v_Mail_Conn, ' name="');
		  utl_smtp.write_raw_data(v_Mail_Conn,utl_raw.cast_to_raw(MAIL_PKG.attachments(x).name));
          utl_smtp.write_data(v_Mail_Conn, '"' || crlf);
          utl_smtp.write_data(v_Mail_Conn, 'Content-Transfer-Encoding: base64'|| crlf );
          utl_smtp.write_data(v_Mail_Conn, 'Content-Disposition: attachment;'|| crlf );
          utl_smtp.write_data(v_Mail_Conn, ' filename="' || MAIL_PKG.ENCODE(MAIL_PKG.attachments(x).name) || '"' || crlf);
          utl_smtp.write_data(v_Mail_Conn, crlf );
и замените вот на это:
          utl_smtp.write_data(v_Mail_Conn, '--'|| boundary || crlf );
		  IF message IS NOT NULL OR x!=1 THEN
            utl_smtp.write_data(v_Mail_Conn, 'Content-Type: '||MAIL_PKG.attachments(x).mimetype||';'|| crlf );
            utl_smtp.write_data(v_Mail_Conn, ' name="');
	        utl_smtp.write_raw_data(v_Mail_Conn,utl_raw.cast_to_raw(MAIL_PKG.attachments(x).name));
            utl_smtp.write_data(v_Mail_Conn, '"' || crlf);
            utl_smtp.write_data(v_Mail_Conn, 'Content-Transfer-Encoding: base64'|| crlf );
            utl_smtp.write_data(v_Mail_Conn, 'Content-Disposition: attachment;'|| crlf );
            utl_smtp.write_data(v_Mail_Conn, ' filename="' || MAIL_PKG.ENCODE(MAIL_PKG.attachments(x).name) || '"' || crlf);
		  ELSE
           utl_smtp.write_data(v_Mail_Conn, 'Content-Type: '||MAIL_PKG.attachments(x).mimetype||'; charset="utf-8"'|| crlf );
           utl_smtp.write_data(v_Mail_Conn, 'Content-Transfer-Encoding: base64'|| crlf );
          END IF;			
          utl_smtp.write_data(v_Mail_Conn, crlf );

Я протестировал этот код на бате, на других клиентах пока нет времени. Если указать мимтип text/plain атача - бат понимает сразу как обычное письмо. если как text/html - то выводит как вложеный файл Письмо.htm - скорее всего это особенность бата так отображать хтмл письма, другие клиенты думаю нормально воспримут. Кодировка атачнутого письма utf-8. Если необходимо, поправьте в куске кода выше. Отпишитесь, пожалуйста, получилось или нет. Если все получится, то доработаю пакет под это
29 ноя 10, 08:31    [9854110]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
Uncle Tola
Member

Откуда:
Сообщений: 86
chameleon82,

Спасибо!
Под MS Outlook 2007 все нормально.
29 ноя 10, 09:29    [9854245]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
Uncle Tola
Member

Откуда:
Сообщений: 86
Здравствуйте!

Никак не получается отправить сообщение на русском.
Пишу на русском текст, кладу его в сообщение (больше 32К, через BLOB). Однако все русские символы удаляются (но знаки препинания и английские символы остаются).

Скажите, это что то в настройках кодировки базы данных ?

Заголовок на русском языке нормально обрабатывается, одноко русские символы в теле он чистит :)
15 дек 10, 16:44    [9943539]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
-2-
Member

Откуда:
Сообщений: 12953
Uncle Tola,

Стоит уточнить версию БД - может все эти испражнения с самописьками и не нужны.
15 дек 10, 17:33    [9944027]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
Uncle Tola
Member

Откуда:
Сообщений: 86
9.2.0.8
15 дек 10, 17:42    [9944120]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
попробуйте формировать blob в кодировке utf-8, соответственно при отправке кодировку атачмента указывать тоже utf-8. Должно работать.
16 дек 10, 11:06    [9947189]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
Uncle Tola
Member

Откуда:
Сообщений: 86
chameleon82
попробуйте формировать blob в кодировке utf-8, соответственно при отправке кодировку атачмента указывать тоже utf-8. Должно работать.


Спасибо.

Как оказалось ничего менять в коде не надо.
Надо только перед тем как записывать в BLOB делать конвертацию:

vText := Convert(vMailText, 'UTF8');
16 дек 10, 17:30    [9950618]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
wellvk
Member

Откуда: Новосибирск
Сообщений: 424
Всех приветствую, скажите, а в само тело письма можно вставить картинку(*.jpeg), например в кодировки Base64?, не вложенный файл а картинку. Попробовал через bfile, приходит
2F396A2F34414151536B5A4A526741424151454159414267414...
4 апр 11, 16:00    [10468486]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
wellvk
Всех приветствую, скажите, а в само тело письма можно вставить картинку(*.jpeg), например в кодировки Base64?, не вложенный файл а картинку. Попробовал через bfile, приходит
2F396A2F34414151536B5A4A526741424151454159414267414...


Могу ошибаться, но кажется, такое невозможно.

Для вставки картинки в текст нужно делать следующее: формат письма html, сначала делаем вложение картинки, имя файла даем например my_image.jpg (имя файла, которое должно прийти в письме), затем в теле письма пишем хтмл-код примерно такой:
<h1>Письмо с картинкой</h2>
<img src="my_image.jpg">
5 апр 11, 06:18    [10471115]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
wellvk
Member

Откуда: Новосибирск
Сообщений: 424
chameleon82, тоесть, если даже картинку перевести в base64, почта(почтовые клиенты) не смогут интерпретировать её?!(жаль, идея была хорошая).
5 апр 11, 06:52    [10471121]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
wellvk, Если спецификация позволяет вкладывать файл вместо тела письма, то можно. К сожалению,я не изучал этот вопрос в спецификациях, попробуйте поправить пакет.
5 апр 11, 07:28    [10471137]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
мимо шел
Guest
wellvk,

<img src="data:image/gif;base64,R0lGODlhDwAPAJECAAAAAP//AAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFCgACACwAAAAADwAPAAAENFBICWqdWNTA+cVAJ3pTOI4A5ZnB1mpebM7sKbr2Xectbf0kH/AFW1k6KVUuWdp9MppfJgIAIfkEBQoAAgAsAwADAAkABgAABBNQACDqlCFQkHkNAhhWZGmWU6pGADs%3D">
5 апр 11, 07:57    [10471151]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
TrueRus
Guest
Дата формируется не по стандарту RFC2822. Из-за этого некоторые клиенты отпраляют письма в нежелатеьную почту

to_char([b]cast[/b] (date$d as timestamp [b]with time zone[/b]),
                 'Dy, DD Mon YYYY hh24:mi:ss [b]TZHTZM[/b]',
                 'NLS_DATE_LANGUAGE = ''american''');
12 апр 11, 13:46    [10506111]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
проходя_мимо
Guest
-2-
Uncle Tola,

Стоит уточнить версию БД - может все эти испражнения с самописьками и не нужны.

А что, в 11g есть готовое решение ?
12 апр 11, 15:13    [10506879]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
-2-
Member

Откуда:
Сообщений: 12953
проходя_мимо,

Для больше 32к нет, почти. Есть уже загруженный в сиса пакет javax.mail.
12 апр 11, 15:29    [10507015]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
_Ildar_
Member

Откуда: Astrakhan
Сообщений: 310
_Ildar_,

Есть вопрос. Если используется Exchange 2010, а он требует авторизации, то как это сделать с помощью вышеуказанного пакета?

Спасибо!
17 май 11, 13:28    [10664309]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
_Ildar_
_Ildar_,

Есть вопрос. Если используется Exchange 2010, а он требует авторизации, то как это сделать с помощью вышеуказанного пакета?

Спасибо!


С exchange не работал, но по идее если авторизация smtp должно работать:
 BEGIN
	 MAIL_PKG.SET_MAILSERVER ('localhost',25);
	 MAIL_PKG.SET_AUTH ('e.petrov','password');
        MAIL_PKG.SEND( 'a.ivanov@yourcomany.ru','Test subject', 'Some message!');
  END;
18 май 11, 10:41    [10669483]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
andreymx
Member

Откуда: Запорожье
Сообщений: 41790
chameleon82
Всем спасибо за подсказки.
Я в свою очередь обновил пакет, добавил возможность вставлять блобы (из базы или сформированные вручную).
Выкладываю обновленную версию целиком:
...
 PROCEDURE SEND ( mailto IN VARCHAR2
				, subject IN VARCHAR2
				, message IN VARCHAR2
                , mailfrom IN VARCHAR2 DEFAULT NULL
				, mimetype IN VARCHAR2 DEFAULT 'text/plain'
				, priority IN NUMBER DEFAULT NULL
                )
 IS
...
   amt CONSTANT BINARY_INTEGER := 48; -- 48bytes binary convert to 128bytes of base64.
...
 BEGIN

...	
	--Attachments
	IF MAIL_PKG.attachments.count>0 THEN
	  FOR x IN 1 .. MAIL_PKG.attachments.count LOOP
   ...
             ps:=1; v_amt:=amt;
		     LOOP
		       BEGIN
		         dbms_lob.read (vFile, v_amt, ps, vRAW);
			     ps := ps + v_amt;
                 utl_smtp.write_raw_data(v_Mail_Conn, UTL_ENCODE.base64_encode(vRAW));

изменение параметра amt с 48 до, например, 960, повышает скорость отправки писем с вложениями раз в 10..20.
13 янв 12, 11:11    [11897625]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
bgrena
Member

Откуда:
Сообщений: 1
chameleon82
.. свою очередь обновил пакет, добавил возможность вставлять блобы (из базы или сформированные вручную).
Выкладываю обновленную версию целиком:

Спасибо за превосходный пакет. Получил удовольствие. Мне не хватает только переходника
от внешних файлов (OS) к блобам
24 май 12, 18:33    [12610293]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
bgrena
Спасибо за превосходный пакет. Получил удовольствие. Мне не хватает только переходника
от внешних файлов (OS) к блобам


Спасибо. А разве этого не достаточно?
 -- Add attachment from file 
	 MAIL_PKG.ADD_ATTACHMENT( 'MYFILEDIR'
							 ,'myfile.jpeg'
							 ,'image/jpeg'
							);


Создать директорию просто:
CREATE DIRECTORY MYFILEDIR AS "c:\tempfiles\";


Если шаблоны писем храните в файлах, запихать их в блоб тоже несложно:
DECLARE
  src_lob  BFILE := BFILENAME('MYFILEDIR', '/tmp/mail.tpl');
  dest_lob BLOB;
BEGIN
  DBMS_LOB.OPEN(src_lob, DBMS_LOB.LOB_READONLY);
  DBMS_LOB.LoadFromFile( DEST_LOB => dest_lob,
                         SRC_LOB  => src_lob,
                         AMOUNT   => DBMS_LOB.GETLENGTH(src_lob) );
  DBMS_LOB.CLOSE(src_lob);
END;
25 май 12, 09:42    [12612382]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
sinitsa
Member

Откуда:
Сообщений: 204
chameleon82,

спасибо, мне тоже актуально, почерпну из Вашего опыта :)
переделаю только под utl_tcp от utl_smtp уже мало что осталось.

от себя могу сказать, есть у нас похожее решение на перле ( не для базы ),
теги тоже "руками" проставляются, иногда письма режут фильтры безопасников,
происходит потому, что теги "нестандартные",
т.е. они соответствуют rfc, но фильтры заточены под outlook.
т.е. в письмо надо вставлять не нужные теги чтобы оно было похоже
на outlook'овское, во всяком случае у нас тут.
25 май 12, 10:24    [12612819]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
Ден
Member

Откуда: Москва
Сообщений: 2073
вот уже готовый пример на java, гдето скачал, отлично работает

К сообщению приложен файл (SendMail.jvs - 5Kb) cкачать
25 май 12, 10:42    [12613084]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
Ден
Member

Откуда: Москва
Сообщений: 2073


К сообщению приложен файл (SENDMAILJPKG.pkb - 3Kb) cкачать
25 май 12, 10:45    [12613124]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
Ден
Member

Откуда: Москва
Сообщений: 2073


К сообщению приложен файл (SENDMAILJPKG.pks - 895bytes) cкачать
25 май 12, 10:46    [12613134]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
andreymx
Member

Откуда: Запорожье
Сообщений: 41790
заменили
    utl_smtp.write_data(v_Mail_Conn, 'Date: ' || TO_CHAR(SYSDATE,     'Dy, DD Mon YYYY hh24:mi:ss',       'NLS_DATE_LANGUAGE = ''american''') || crlf);

на
    utl_smtp.write_data(v_Mail_Conn, 'Date: ' || TO_CHAR(SYSTIMESTAMP,'Dy, DD Mon YYYY HH24:MI:SS TZHTZM','NLS_DATE_LANGUAGE = ''american''') || crlf);
тайм-зону добавили
17 июл 12, 11:04    [12876429]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
Bodyaya
Member

Откуда:
Сообщений: 1
Добрый день!
Есть решение для отправки вложений (BLOB) больше 32к. В курсоре у меня перебираются вложения (их может быть много в одном письме и какждое из них может быть любого размера). В моем случае тестировал на JPEG до 1,6 Мб - больше стало лень:)

procedure do_email_files(from_name varchar2,
                      to_names varchar2,
                      subject varchar2,
                      clob_html_message clob,
                      b_id_email_body number)
is

   smtp_host          varchar2(256) := '*****';
   smtp_port          number := 25;

   boundary           constant varchar2(256) := 'CES.Boundary.DACA587499938898';

   recipients         varchar2(32767);
   directory_path     varchar2(256);
   file_path          varchar2(256);
   mime_type          varchar2(256);
   file_name          varchar2(256);
   cr                 varchar2(1) := chr(13);
   lf                 varchar2(1) := chr(10);
   crlf               varchar2(2) := cr || lf;
   mesg               varchar2(32767);
   conn               UTL_SMTP.CONNECTION;
   i                  binary_integer;
   my_code            number;
   my_errm            varchar2(32767
Begin

..........

     for i in (select * from email_att e where e.id_email_body = b_id_email_body) loop

         if i.attachment is null then
            exit;
         end if;
         if mime_type is null then
            mime_type := 'text/plain';
         end if;

         mesg := crlf || '--' || boundary || crlf;
         mesg := mesg || 'Content-Type: ' || mime_type ||
            '; name="' || i.att_name || '"' || crlf ||
            'Content-Disposition: attachment; filename="' ||
            i.att_name || '"' || crlf ||
            'Content-Transfer-Encoding: base64' || crlf || crlf ;
         utl_smtp.write_data(conn,mesg);

         append_file(null,i.att_name,mime_type,conn,blob_attach => i.attachment);

      end loop;


   mesg := crlf || '--' || boundary || '--' || crlf;
   utl_smtp.write_data(conn,mesg);


   utl_smtp.close_data(conn);
   utl_smtp.quit(conn);

..................
..................


   PROCEDURE append_file(
      directory_path IN VARCHAR2 default null,
      file_name IN VARCHAR2 default null,
      mime_type IN VARCHAR2,
      conn IN OUT UTL_SMTP.CONNECTION,
      clob_attach IN CLOB default null,
      blob_attach IN BLOB default null) IS

      file_handle     utl_file.file_type;
      bfile_handle    bfile;
      lob_len         number(38) := 0;
      lob_pos         number(38) := 1;
      read_bytes      number(38);
      lf_at           number(38);
      line            varchar2(32767); 
      data            raw(32767);
      my_code         number;
      my_errm         varchar2(32767);

   begin

      begin
   
.........................


         if clob_attach is not null then
            lob_len := dbms_lob.getlength(clob_attach);
         elsif blob_attach is not null then
            lob_len := dbms_lob.getlength(blob_attach);
         end if;
   
 
         loop

            if directory_path is not null and substr(mime_type,1,4) = 'text' then
               utl_file.get_line(file_handle,line);
               utl_smtp.write_data(conn,line || crlf);

            else


               if clob_attach is not null then
                  lf_at := dbms_lob.instr(clob_attach,lf,lob_pos);
                  if lf_at = 0 then
                     lf_at := lob_len + 1;
                  end if;
                  read_bytes := lf_at - lob_pos;
                  if read_bytes > 0
                     and dbms_lob.substr(clob_attach,1,lf_at-1) = cr then
                     read_bytes := read_bytes - 1;
                  end if;
                  if read_bytes > 0 then
                     dbms_lob.read(clob_attach,read_bytes,lob_pos,line);
--                     utl_smtp.write_data(conn,line);
                     utl_smtp.write_raw_data(conn,UTL_RAW.CAST_TO_RAW(line));
                  end if;
                  utl_smtp.write_data(conn,crlf);
                  lob_pos := lf_at + 1;

               else
                  if lob_pos + 57 - 1 > lob_len then
                     read_bytes := lob_len - lob_pos + 1;
                  else
                     read_bytes := 57;
                  end if;
                  if blob_attach is not null then
                     dbms_lob.read(blob_attach,read_bytes,lob_pos,data);
                  else
                     dbms_lob.read(bfile_handle,read_bytes,lob_pos,data);
                  end if;
                  utl_smtp.write_raw_data(conn,utl_encode.base64_encode(data));
                  lob_pos := lob_pos + read_bytes;
               end if;

               if lob_pos > lob_len then
                  exit;
               end if;

            end if;
      
         end loop;

..............................
..............................


Код можно подогнать под свой пакет.
Сам его собирал по кусочкам :)
22 авг 12, 11:15    [13047744]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
В пакете уже есть эта возможность (т.е. отправлять неограниченное число файлов over 32kb)
30 авг 12, 08:18    [13086409]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
seregaLOKI
Member

Откуда:
Сообщений: 4
chameleon82, возникла такая проблема. Есть необходимости передать в mesage текст более 32к символов. Использую CLOB, база имеет настройку NLS_CHARACTERSET CL8MSWIN1251. При конверте русских символов в UTF8 в разделе --Message мы на выходе получаем бред.
11 сен 12, 11:41    [13144620]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
Обновил пакет, message теперь clob, поэтому если формировать текст размером больше 32кб без вложений, проблем не должно возникнуть, заодно пофиксил некоторые баги, спасибо andreymx.

CREATE OR REPLACE PACKAGE MAIL_PKG IS
-- --------------------------------------------------------------------------
-- Name         : MAIL_PKG
-- Author       : Nekrasov Alexander
-- Description  : Mail package, send email with attachments
-- Ammedments   :
--   When         Who         What
--   ===========  ==========  =================================================
--   22-JAN-2010  Nekrasov A.  Initial Creation
--   26-MAY-2010  Nekrasov A.  Update package bugs
--   11-OCT-2010  Nekrasov A.  Add Blob attachments
--   10-SEP-2012  Nekrasov A.  Upd. Message type varchar2>clob
-- --------------------------------------------------------------------------

/* EXAMPLE:

 1) Short text email
    BEGIN
      MAIL_PKG.SEND( 'a.ivanov@yourcomany.ru','Test subject', 'Some message!');
    END;

 2) Send mail with text message over 32kbytes formed with CLOB 
    DECLARE 
      v clob:='Some text message over 32kb'||chr(10)||chr(13);
      t varchar2(255):=' The quick brown fox jumps over the lazy dog. '
                     ||' The quick brown fox jumps over the lazy dog. '
                     ||' The quick brown fox jumps over the lazy dog. '||chr(10)||chr(13);
    BEGIN
      for x in 1..300 loop
        v:=v||to_char(x)||' '||t;
      end loop;
      MAIL_PKG.SEND( 'a.ivanov@yourcompany.ru','Test subject', v);
    END ;  

 3) Send mail with message over 32kbytes formed with BLOB
    DECLARE
      vBlob BLOB;
      BEGIN
     SELECT file_data INTO vBlob FROM FND_LOBS WHERE FILE_ID = 161005;                        
     MAIL_PKG.ADD_ATTACHMENT( vBlob
                             ,'MessageOver32kb.htm'
                             ,'text/html'
                            );                            
      MAIL_PKG.SEND( 'a.ivanov@yourcomany.ru','Big message', NULL);    
    END;
    
 4) Extension Email with attacments
    DECLARE
      vBlob BLOB;
    BEGIN
     MAIL_PKG.SET_MAILSERVER ('localhost',25);
     MAIL_PKG.SET_AUTH ('a.nekrasov','password');

     -- Add attachment from file 
     MAIL_PKG.ADD_ATTACHMENT( 'ODPDIR'
                             ,'girl3d.jpeg'
                             ,'image/jpeg'
                            );

     -- Add attachment from BLOB    
     SELECT file_data INTO vBlob FROM FND_LOBS WHERE FILE_ID = 161005;                        
     MAIL_PKG.ADD_ATTACHMENT( vBlob
                             ,'ReportResult.htm'
                             ,'text/html'
                            );                            

     MAIL_PKG.SEND( mailto => 'A. Ivanov <a.ivanov@yourcomany.ru>, O.Petrov <o.petrov@yourcompany.ru>'
                  , subject => 'Test subject'
                  , message => 'Some <b>bold</b> message!'
                  , mailfrom => 'Oracle Notify <no-reply@yourcompany.ru>'
                  , mimetype => 'text/html'
                  , priority => 1
                  );
    END;
*/

 POP3 CONSTANT VARCHAR2(4):='POP3';
 SMTP CONSTANT VARCHAR2(4):='SMTP';
 IMAP CONSTANT VARCHAR2(4):='IMAP';

 DEBUG BOOLEAN := FALSE;

 -- SET_MAILSERVER:
 --  Set up mail server for send emails. Default Localhost
 -- IN
 -- MAILSERVER is ip or url of mail server
 -- MAILPORT is port for mail server. Default 25
 PROCEDURE SET_MAILSERVER ( mailserver varchar2
                          , mailport number default 25
                          );

 -- SET_AUTH
 --  Set authorization on smtp server
 -- IN
 -- AUTH_USER is authorization user
 -- AUTH_PASS is password for AUTH_USER
 --
 -- Execute SET_AUTH(); -- for disable authorization
 PROCEDURE SET_AUTH (  auth_user varchar2 default null
                     , auth_pass varchar2 default null
                          );

 -- ENCODE:
 --  Encodes string to email compatible view
 -- IN
 -- STR is string to convert
 -- TP is type of convert:
 --    B - is base64 encoding
 FUNCTION ENCODE( str IN VARCHAR2
                , tp IN VARCHAR2 DEFAULT 'Q') RETURN VARCHAR2;

 -- PREPARE
 --  Prepare configs for email.
 PROCEDURE PREPARE;

 -- ADD_RCPT
 --  Add recipient to recipients list exploded by  ','
 -- STR is variable with recipients
 -- RCPTMAIL is recipient mail added to STR
 -- RCPTNAME is recipient name added to STR
 -- Example: str='user1@domain.ru' rcptmail='user2@domain.ru'
 --  after => str='user1@domain.ru, user2@domain.ru'
 PROCEDURE ADD_RCPT( str IN OUT VARCHAR2
                   , rcptmail IN VARCHAR2
                   , rcptname IN VARCHAR2 DEFAULT NULL);

 -- ADD_ATTACHMENT
 --  Add file-attachment to attachments list to email
 -- IN
 -- DIRNAME is logical link to access physical directories of server. See DBA_DIRECTORIES table
 -- FILENAME is name of file to attach
 -- MIMETYPE is mime-type for sended file
 -- NAME is name for attached file for email. Default eq FILENAME
 PROCEDURE ADD_ATTACHMENT ( dirname IN varchar2
                          , filename IN varchar2
                          , mimetype IN varchar2 DEFAULT 'text/plain'
                          , name IN varchar2 DEFAULT NULL
                           );
 -- ADD_ATTACHMENT
 --  Add blob-attachment to attachments list to email
 -- IN
 -- BLOBLOC - Blob locator for attached blob
 -- FILENAME is name of file to attach
 -- MIMETYPE is mime-type for sended file
 PROCEDURE ADD_ATTACHMENT ( blobloc IN blob
                          , filename IN varchar2
                          , mimetype IN varchar2 DEFAULT 'text/html'
                           );
                           
 -- SEND
 --  Send email with attachments to recipient
 -- IN
 -- MAILTO is name and email addresses of recipients ( ex. "user@domain.com"
 --       , "User Name <user@domain.com>", "User1 <user1@domain>, User2 <user2@domain>")
 -- SUBJECT is subject of email
 -- MESSAGE is message of email
 -- MAILFROM is name and email of sender. (ex. "no-reply@domain", "Notify system <no-reply@domain>")
 -- MIMETYPE is mime-type of message. Available values is 'text/plain' and 'text/html'
 -- PRIORITY is priority of mail (1 - High, 2 - Highest, 3 - Normal, 4 - Lowest, 5 - Low)
 PROCEDURE SEND ( mailto IN VARCHAR2
                , subject IN VARCHAR2
                , message IN CLOB
                , mailfrom IN VARCHAR2 DEFAULT NULL
                , mimetype IN VARCHAR2 DEFAULT 'text/plain'
                , priority IN NUMBER DEFAULT NULL
                );

END MAIL_PKG;
/

CREATE OR REPLACE PACKAGE BODY MAIL_PKG
IS

 mailserver VARCHAR2(30):='localhost';
 mailport INTEGER:=25;
 auth_user VARCHAR2(50);
 auth_pass VARCHAR2(50);
 crlf         VARCHAR2(2)  := utl_tcp.CRLF; -- chr(13)||chr(10);

 type attach_row is record ( dirname varchar2(30)
                           , filename  varchar2(30)
                           , name  varchar2(30)
                           , mimetype varchar2(30)
                           , blobloc blob
                           , attachtype varchar2(30)
                           );
 type attach_list is table of attach_row;
 attachments attach_list;

 type rcpt_row is record ( rcptname varchar2(100)
                     , rcptmail varchar2(50)
                     );
 type rcpt_list is table of rcpt_row;

 PROCEDURE SET_MAILSERVER ( mailserver varchar2
                          , mailport number default 25
                          ) IS
 BEGIN
  MAIL_PKG.mailserver := mailserver;
  MAIL_PKG.mailport := mailport;
 END;

 PROCEDURE SET_AUTH (  auth_user varchar2 default null
                     , auth_pass varchar2 default null
                          ) IS
 BEGIN
   MAIL_PKG.auth_user := auth_user;
   MAIL_PKG.auth_pass := auth_pass;
 END;

 FUNCTION ENCODE(str IN VARCHAR2, tp IN VARCHAR2 DEFAULT 'Q') RETURN VARCHAR2 IS
 BEGIN
   -- ToDo: UTL_ENCODE.QUOTED_PRINTABLE | UTL_ENCODE.BASE64
   IF tp='B' THEN
     RETURN '=?utf-8?b?'|| UTL_RAW.cast_to_varchar2(UTL_ENCODE.base64_encode(UTL_RAW.cast_to_raw (CONVERT (SUBSTR(str,1,24), 'UTF8'))))|| '?='
         || CASE WHEN SUBSTR(str,25) IS NOT NULL THEN crlf || ' '|| ENCODE(SUBSTR(str,25),tp) END;
   ELSIF tp='Q' THEN
     RETURN '=?utf-8?q?' || UTL_RAW.cast_to_varchar2(utl_encode.QUOTED_PRINTABLE_ENCODE(utl_raw.cast_to_raw(CONVERT (SUBSTR(str,1,8), 'UTF8') ))) || '?='
         || CASE WHEN SUBSTR(str,9) IS NOT NULL THEN crlf || ' '|| ENCODE(SUBSTR(str,9),tp) END;
   ELSE
     RETURN str;
   END IF;
 END;

 PROCEDURE PREPARE
 IS
 BEGIN
   MAIL_PKG.attachments:=MAIL_PKG.attach_list();
 END;

 PROCEDURE ADD_RCPT( str IN OUT VARCHAR2
                   , rcptmail IN VARCHAR2
                   , rcptname IN VARCHAR2 DEFAULT NULL) IS
  rcpt varchar2(255);
 BEGIN
  rcpt:=CASE WHEN rcptname is null THEN
          rcptmail
        ELSE
          trim(replace(replace(rcptname,',',' '),';',' '))||' <'|| rcptmail ||'>'
        END;
  IF trim(str) is NULL THEN
     str :=  trim(rcpt);
  ELSE
     str := str||', '||trim(rcpt);
  END IF;
 END;

 PROCEDURE ADD_ATTACHMENT ( dirname IN varchar2
                          , filename IN varchar2
                          , mimetype IN varchar2 DEFAULT 'text/plain'
                          , name IN varchar2 DEFAULT NULL
                           )
 IS
  v_fl BFILE :=BFILENAME(dirname,filename);
 BEGIN
   IF DBMS_LOB.FILEEXISTS (v_fl)=1 THEN
      MAIL_PKG.attachments.extend;
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).dirname:=dirname;
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).filename:=filename;
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).name:=nvl(name,filename);
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).mimetype:=mimetype;
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).attachtype:='FILE';      
   ELSE
      RAISE_APPLICATION_ERROR(-20001, 'File is not exists');
   END IF;
 END;
 
 PROCEDURE ADD_ATTACHMENT ( blobloc IN blob
                          , filename IN varchar2
                          , mimetype IN varchar2 DEFAULT 'text/html'
                           )
 IS 
 BEGIN
      MAIL_PKG.attachments.extend;
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).name:=filename;
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).mimetype:=mimetype;
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).blobloc:=blobloc;      
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).attachtype:='BLOB';      
 END;                            
 

 FUNCTION CREATE_RCPT_LIST(mailto IN VARCHAR2) RETURN MAIL_PKG.rcpt_list IS
  v_mailto VARCHAR2(4096) := replace(mailto,';',',')||',';
  pntr INTEGER;
  buf VARCHAR2(255);
  rcptmail VARCHAR2(255);
  rcptlist MAIL_PKG.rcpt_list:=MAIL_PKG.rcpt_list();
 BEGIN
  FOR maxrcptnts IN 1..50
  LOOP
     pntr:=INSTR(v_mailto,','); buf := substr(v_mailto,1,pntr-1);
     IF pntr>0 THEN
       IF INSTR(buf,'<')>0 AND INSTR(buf,'>')>0 THEN
         rcptmail:= SUBSTR(buf,INSTR(buf,'<')+1,INSTR(SUBSTR(buf,INSTR(buf,'<')+1),'>')-1);
         IF rcptmail IS NOT NULL THEN
            rcptlist.extend;
            rcptlist(rcptlist.count).rcptmail := TRIM(rcptmail);
            rcptlist(rcptlist.count).rcptname := TRIM(SUBSTR(buf,1,INSTR(buf,'<')-1));
         END IF;
       ELSE
         rcptmail := TRIM(buf);
         IF rcptmail IS NOT NULL THEN
           rcptlist.extend;
           rcptlist(rcptlist.count).rcptmail:= TRIM(rcptmail);
         END IF;
       END IF;
     ELSE
       EXIT;
     END IF;
     v_mailto := substr(v_mailto,pntr+1);
   END LOOP;
   RETURN rcptlist;
 END;

 PROCEDURE SEND ( mailto IN VARCHAR2
                , subject IN VARCHAR2
                , message IN CLOB
                , mailfrom IN VARCHAR2 DEFAULT NULL
                , mimetype IN VARCHAR2 DEFAULT 'text/plain'
                , priority IN NUMBER DEFAULT NULL
                )
 IS
   v_Mail_Conn  utl_smtp.Connection;
   boundary VARCHAR2(50) := '-----7D81B75CCC90DFRW4F7A1CBD';
   vFile BFILE;
   vRAW RAW(32767);
   amt CONSTANT BINARY_INTEGER := 10368; -- 48bytes binary convert to 128bytes of base64. (32767/2 max for raw convert)
   v_amt BINARY_INTEGER;
   ps BINARY_INTEGER := 1;
   message_part varchar2(32767);
   v_mime VARCHAR2(30);
   reply UTL_SMTP.REPLY;
   replies UTL_SMTP.REPLIES;
   rcptlist MAIL_PKG.rcpt_list;
   sndr MAIL_PKG.rcpt_row;
 BEGIN
    rcptlist:=create_rcpt_list(mailto);
    IF rcptlist.count=0 THEN
      RAISE_APPLICATION_ERROR(-20001, 'Recipients requered');
    END IF;
    IF mimetype<>'text/html' and mimetype<>'text/plain' THEN
      RAISE_APPLICATION_ERROR(-20001, 'MimeType must be "text/html" or "text/plain"');
    ELSE
      v_mime:=mimetype;
    END IF;
    v_Mail_Conn := utl_smtp.Open_Connection(MAIL_PKG.mailserver, MAIL_PKG.mailport);
    replies:=utl_smtp.Ehlo(v_Mail_Conn,MAIL_PKG.mailserver);
    if create_rcpt_list(mailfrom).count>0 then
      sndr := create_rcpt_list(mailfrom)(1);
    else
      sndr := create_rcpt_list( 'mail@' || UTL_INADDR.GET_HOST_NAME )(1); -- host from oracle-server
      -- sndr := create_rcpt_list( 'mail@' || substr(replies(1).text,1,instr(replies(1).text,' ')-1))(1); -- Addr from ehlo answer
    end if;

    if mail_pkg.auth_user is not null then
       for x IN 1 .. replies.count loop
          IF INSTR(replies(x).text,'AUTH')>0 then -- If server supply authorization
            utl_smtp.command(v_Mail_Conn, 'AUTH LOGIN');
            utl_smtp.command(v_Mail_Conn,utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(auth_user))));
            utl_smtp.command(v_Mail_Conn,utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(auth_pass))));
            exit;
         END IF;
       end loop;
    end if;

    utl_smtp.Mail(v_Mail_Conn, sndr.rcptmail);
    FOR rcpts IN 1 .. rcptlist.count
    LOOP
      utl_smtp.Rcpt(v_Mail_Conn, rcptlist(rcpts).rcptmail);
    END LOOP;

    utl_smtp.open_data(v_Mail_Conn); -- open data sheet
    utl_smtp.write_data(v_Mail_Conn, 'Date: ' || TO_CHAR(SYSTIMESTAMP,'Dy, DD Mon YYYY HH24:MI:SS TZHTZM','NLS_DATE_LANGUAGE = ''american''') || crlf);
    utl_smtp.write_data(v_Mail_Conn, 'From: ');
    if sndr.rcptname is not null then
        utl_smtp.write_data(v_Mail_Conn, MAIL_PKG.ENCODE(sndr.rcptname) ||' <'|| sndr.rcptmail || '>');
    else
        utl_smtp.write_data(v_Mail_Conn, sndr.rcptmail);
    end if;
    utl_smtp.write_data(v_Mail_Conn, crlf );
    utl_smtp.write_data(v_Mail_Conn, 'Subject: '|| MAIL_PKG.ENCODE(subject) || crlf );
    utl_smtp.write_data(v_Mail_Conn, 'To: ');
    FOR rcpts IN 1 .. rcptlist.count
    LOOP
      if rcpts>1 then
       utl_smtp.write_data(v_Mail_Conn, ',');
      end if;
      if rcptlist(rcpts).rcptname is not null then
        utl_smtp.write_data(v_Mail_Conn, MAIL_PKG.ENCODE(rcptlist(rcpts).rcptname) ||' <'|| rcptlist(rcpts).rcptmail || '>');
      else
        utl_smtp.write_data(v_Mail_Conn, rcptlist(rcpts).rcptmail);
      end if;
    END LOOP;
    utl_smtp.write_data(v_Mail_Conn, crlf );

    IF priority IS NOT NULL and priority BETWEEN 1 AND 5 THEN
      utl_smtp.write_data(v_Mail_Conn, 'X-Priority: ' || priority || crlf );
    END IF;
    utl_smtp.write_data(v_Mail_Conn, 'MIME-version: 1.0' || crlf );
    utl_smtp.write_data(v_Mail_Conn, 'Content-Type: multipart/mixed;'|| crlf );
    utl_smtp.write_data(v_Mail_Conn, ' boundary="'||boundary||'"'|| crlf );
    utl_smtp.write_data(v_Mail_Conn, crlf );
 
    --Message
    IF message IS NOT NULL THEN    
    utl_smtp.write_data(v_Mail_Conn, '--'|| boundary || crlf );
    utl_smtp.write_data(v_Mail_Conn, 'Content-Type: '||v_mime||'; charset="utf-8"'|| crlf );
    utl_smtp.write_data(v_Mail_Conn, 'Content-Transfer-Encoding: 8bit'|| crlf );
    utl_smtp.write_data(v_Mail_Conn, crlf );
    -- utl_smtp.write_raw_data(v_Mail_Conn, utl_raw.cast_to_raw(CONVERT(message,'UTF8')));
    ps:=1; v_amt:=amt;
    LOOP
      BEGIN
        dbms_lob.read(message, v_amt, ps, message_part);
        ps := ps + v_amt;
        utl_smtp.write_raw_data(v_Mail_Conn, utl_raw.cast_to_raw(CONVERT(message_part,'UTF8')));                 
      EXCEPTION
        WHEN no_data_found THEN
             EXIT;
      END;            
    END LOOP; 
    utl_smtp.write_data(v_Mail_Conn, crlf );
    utl_smtp.write_data(v_Mail_Conn, crlf );
    END IF;
    
    --Attachments
    IF MAIL_PKG.attachments.count>0 THEN
      FOR x IN 1 .. MAIL_PKG.attachments.count LOOP
          utl_smtp.write_data(v_Mail_Conn, '--'|| boundary || crlf );
          -- HOTFIX
          IF message IS NOT NULL OR x!=1 THEN
            utl_smtp.write_data(v_Mail_Conn, 'Content-Type: '||MAIL_PKG.attachments(x).mimetype||';'|| crlf );
            utl_smtp.write_data(v_Mail_Conn, ' name="');
            utl_smtp.write_raw_data(v_Mail_Conn,utl_raw.cast_to_raw(MAIL_PKG.attachments(x).name));
            utl_smtp.write_data(v_Mail_Conn, '"' || crlf);
            utl_smtp.write_data(v_Mail_Conn, 'Content-Transfer-Encoding: base64'|| crlf );
            utl_smtp.write_data(v_Mail_Conn, 'Content-Disposition: attachment;'|| crlf );
            utl_smtp.write_data(v_Mail_Conn, ' filename="' || MAIL_PKG.ENCODE(MAIL_PKG.attachments(x).name) || '"' || crlf);
          ELSE
           utl_smtp.write_data(v_Mail_Conn, 'Content-Type: '||MAIL_PKG.attachments(x).mimetype||'; charset="utf-8"'|| crlf );
           utl_smtp.write_data(v_Mail_Conn, 'Content-Transfer-Encoding: base64'|| crlf );
          END IF;            
          utl_smtp.write_data(v_Mail_Conn, crlf );
          IF MAIL_PKG.attachments(x).attachtype = 'FILE' THEN 
             vFile := BFILENAME(MAIL_PKG.attachments(x).dirname,MAIL_PKG.attachments(x).filename);
             dbms_lob.fileopen(vFile, dbms_lob.file_readonly);
             ps:=1; v_amt:=amt;
             LOOP
               BEGIN
                 dbms_lob.read (vFile, v_amt, ps, vRAW);
                 ps := ps + v_amt;
                 utl_smtp.write_raw_data(v_Mail_Conn, UTL_ENCODE.base64_encode(vRAW));
               EXCEPTION
                 WHEN no_data_found THEN
                   EXIT;
               END;            
             END LOOP;
             dbms_lob.fileclose(vFile);
          ELSIF MAIL_PKG.attachments(x).attachtype = 'BLOB' THEN
               dbms_lob.open(MAIL_PKG.attachments(x).blobloc, dbms_lob.file_readonly);
             ps:=1; v_amt:=amt;
             LOOP
               BEGIN
                 dbms_lob.read (MAIL_PKG.attachments(x).blobloc, v_amt, ps, vRAW);
                 ps := ps + v_amt;
                 utl_smtp.write_raw_data(v_Mail_Conn, UTL_ENCODE.base64_encode(vRAW));
               EXCEPTION
                 WHEN no_data_found THEN
                   EXIT;
               END;            
             END LOOP;
             dbms_lob.close(MAIL_PKG.attachments(x).blobloc);                           
          END IF;                   

          utl_smtp.write_data(v_Mail_Conn, crlf );
          utl_smtp.write_data(v_Mail_Conn, crlf );
      END LOOP;
    END IF;

    -- Final Boundary
    utl_smtp.write_data(v_Mail_Conn, '--' || boundary || '--');

    utl_smtp.close_data(v_Mail_Conn);
    utl_smtp.quit(v_Mail_Conn);

    -- Clear attachments
    MAIL_PKG.attachments:=MAIL_PKG.attach_list();

 EXCEPTION
    WHEN OTHERS THEN
       BEGIN
         MAIL_PKG.attachments:=MAIL_PKG.attach_list();
         utl_smtp.rset(v_Mail_Conn);
         utl_smtp.quit(v_Mail_Conn);
       EXCEPTION WHEN OTHERS THEN NULL;
       END;
    RAISE;
 END;


 
BEGIN
  MAIL_PKG.attachments:=MAIL_PKG.attach_list();
END;
/
12 сен 12, 07:09    [13149338]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
seregaLOKI
Member

Откуда:
Сообщений: 4
chameleon82,

Огромное спасибо!
12 сен 12, 08:02    [13149416]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
Итак, теперь я научил пакет не только отправлять почту, но и принимать ее. Пока еще все достаточно сыровато, но для тех, кто хочет побаловаться, можете поиграться.
Итак, что может пакет:
- Получить список писем во встроенный массив, получить их заголовки (поля "от","кому","тема","дата" для удобства продублированы во встроенные переменные).
- Получить тело сообщения
- Получить вложения! (все вложения представлены как CLOB)
- Распознать у вложения имя файла (впрочем, все заголовки вложения сохраняются в массив)
- Текст вложений декодируется в соответствии с методом и кодовой страницей (не все кодовые страницы проверял) и его можно сразу преобразовывать в BLOB для сохранения или как есть сохранять в базу

Замеченные косяки:
- Письма объемом более 1Мб умирают при получении. Как я понимаю, связано с необходимостью конкатенации CLOB и мелких строк (по 72 байта) до нужного объема. Как победить пока не знаю.
- Пока некорректно определяются вложения (бывают пустые вложения без содержимого. связано с декодировкой boundares, разберусь позже, если кому-то будет необходимо)
- Могут встретиться другие косяки по декодировке текста сообщения и т.п. Для самостоятельной отладки добавил фунцию PDEBUG.

Пример работы с получением почты:
 BEGIN
       MAIL_PKG.DEBUG := TRUE;
       MAIL_PKG.DEBUG_LEVEL := MAIL_PKG.DEBUG_WARNINGS;
       MAIL_PKG.SET_MAILSERVER ('yourmailserver.com');
       MAIL_PKG.SET_AUTH ('a.ivanov','mypass');
       MAIL_PKG.MAIL_CONNECT;
       DBMS_OUTPUT.PUT_LINE('Total mails count:'||mail_pkg.mailbox.count);
       --  MAIL_PKG.GET_HEADERS; -- Get headers for all mails
       
       FOR i IN 1..LEAST(10,mail_pkg.mailbox.count) LOOP -- GET FIRST 10 mails
         MAIL_PKG.GET_MAIL(i,0); -- GET MAIL HEADER
         DBMS_OUTPUT.PUT_LINE('MAIL:'||i || ' (' ||trunc(mail_pkg.mailbox(i).bytes/1024) || 'Kbytes) From:'||mail_pkg.mailbox(i).MailFrom
                              ||' Subject:'||mail_pkg.mailbox(i).Subject
                              );
             
         IF mail_pkg.mailbox(i).bytes>1000000 THEN
           -- Delete mails over 1Mb
           MAIL_PKG.DELETE_MAIL(i);
         ELSE
           MAIL_PKG.GET_MAIL(i);
           DBMS_OUTPUT.PUT_LINE(substr('    Text:' ||mail_pkg.mailbox(i).message,1,255) );         
           DBMS_OUTPUT.PUT_LINE('    Attachments:' ||mail_pkg.mailbox(i).attachments.count);

           IF mail_pkg.mailbox(i).attachments.count>0 THEN
             FOR att IN 1..mail_pkg.mailbox(i).attachments.count LOOP
               -- Real Attachments 
               IF mail_pkg.mailbox(i).attachments(att).hdr.exists('Content-Disposition') 
                 AND INSTR(mail_pkg.mailbox(i).attachments(att).hdr('Content-Disposition'),'attachment')>0               
               THEN
                 DBMS_OUTPUT.PUT_LINE('    filename: '
                    ||mail_pkg.extract_value(mail_pkg.mailbox(i).attachments(att).hdr('Content-Disposition'),'filename')
                    ||', about '||trunc(dbms_lob.getlength(mail_pkg.mailbox(i).attachments(att).content)/1024) ||'Kbytes'                 
                   );
                 -- You can convert this CLOB into BLOB ans save it into database or as file  
                 -- mail_pkg.mailbox(i).attachments(att).content                   
                                    
               END IF; 
               -- Preview includes and text-attachments 
               IF  mail_pkg.mailbox(i).attachments(att).hdr.exists('Content-Type') THEN
                 IF  INSTR(mail_pkg.mailbox(i).attachments(att).hdr('Content-Type'),'text')>0 THEN
                   DBMS_OUTPUT.PUT_LINE(substr('    PreviewAttachmentText:' ||mail_pkg.mailbox(i).attachments(att).content,1,255) );             
                 END IF;
               END IF;  
             END LOOP;
           END IF;                           
         END IF;     
       END LOOP;
   
       MAIL_PKG.MAIL_DISCONNECT;
    EXCEPTION WHEN OTHERS THEN
      -- ANYCASE YOU MUST CLOSE CONNECTION
      MAIL_PKG.MAIL_DISCONNECT;
    END;       
17 сен 12, 13:40    [13175611]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
И, собственно, новая версия пакета.
Принимаю ваши замечания и предложения :)


CREATE OR REPLACE PACKAGE MAIL_PKG IS
-- --------------------------------------------------------------------------
-- Name         : MAIL_PKG
-- Author       : Nekrasov Alexander
-- Description  : Mail package, send email with attachments
-- Url          : http://www.sql.ru/forum/actualthread.aspx?tid=729238
-- Ammedments   :
--   When         Who         What
--   ===========  ==========  =================================================
--   22-JAN-2010  Nekrasov A.  Initial Creation
--   11-OCT-2010  Nekrasov A.  Add Blob attachments
--   17-SEP-2012  Nekrasov A.  Add Receive Emails
-- --------------------------------------------------------------------------

/* EXAMPLE:

 1) Short text email
    BEGIN
      MAIL_PKG.SEND( 'a.ivanov@yourcomany.ru','Test subject', 'Some message!');
	END;

 2) Send mail with text message over 32kbytes formed with CLOB 
    DECLARE 
      v clob:='Some text message over 32kb'||chr(10)||chr(13);
      t varchar2(255):=' The quick brown fox jumps over the lazy dog. '
                     ||' The quick brown fox jumps over the lazy dog. '
                     ||' The quick brown fox jumps over the lazy dog. '||chr(10)||chr(13);
    BEGIN
      for x in 1..300 loop
        v:=v||to_char(x)||' '||t;
      end loop;
      MAIL_PKG.SEND( 'a.ivanov@yourcompany.ru','Test subject', v);
    END ;  

 3) Send mail with message over 32kbytes formed with BLOB
    DECLARE
      vBlob BLOB;
  	BEGIN
	 SELECT file_data INTO vBlob FROM FND_LOBS WHERE FILE_ID = 161005;						
	 MAIL_PKG.ADD_ATTACHMENT( vBlob
							 ,'MessageOver32kb.htm'
							 ,'text/html'
							);							
      MAIL_PKG.SEND( 'a.ivanov@yourcomany.ru','Big message', NULL);	
	END;
	
 4) Extension Email with attacments
    DECLARE
      vBlob BLOB;
    BEGIN
	 MAIL_PKG.SET_MAILSERVER ('localhost',25);
	 MAIL_PKG.SET_AUTH ('a.nekrasov','password');

	 -- Add attachment from file 
	 MAIL_PKG.ADD_ATTACHMENT( 'ODPDIR'
							 ,'girl3d.jpeg'
							 ,'image/jpeg'
							);

	 -- Add attachment from BLOB	
	 SELECT file_data INTO vBlob FROM FND_LOBS WHERE FILE_ID = 161005;						
	 MAIL_PKG.ADD_ATTACHMENT( vBlob
							 ,'ReportResult.htm'
							 ,'text/html'
							);							

	 MAIL_PKG.SEND( mailto => 'A. Ivanov <a.ivanov@yourcomany.ru>, O.Petrov <o.petrov@yourcompany.ru>'
	              , subject => 'Test subject'
				  , message => 'Some <b>bold</b> message!'
				  , mailfrom => 'Oracle Notify <no-reply@yourcompany.ru>'
                  , mimetype => 'text/html'
				  , priority => 1
	              );
	END;
    
 5) Receive emails example:
 
    BEGIN
       MAIL_PKG.DEBUG := TRUE;
       MAIL_PKG.SET_MAILSERVER ('yourmailserver.com');
       MAIL_PKG.SET_AUTH ('a.ivanov','mypass');
       MAIL_PKG.MAIL_CONNECT;
       DBMS_OUTPUT.PUT_LINE('Total mails count:'||mail_pkg.mailbox.count);
       --  MAIL_PKG.GET_HEADERS; -- Get headers for all mails
       
       FOR i IN 1..LEAST(10,mail_pkg.mailbox.count) LOOP -- GET FIRST 10 mails
         MAIL_PKG.GET_MAIL(i,0); -- GET MAIL HEADER
         DBMS_OUTPUT.PUT_LINE('MAIL:'||i || ' (' ||trunc(mail_pkg.mailbox(i).bytes/1024) || 'Kbytes) From:'||mail_pkg.mailbox(i).MailFrom
                              ||' Subject:'||mail_pkg.mailbox(i).Subject
                              );
             
         IF mail_pkg.mailbox(i).bytes>1000000 THEN
           -- Delete mails over 1Mb
           MAIL_PKG.DELETE_MAIL(i);
         ELSE
           MAIL_PKG.GET_MAIL(i);
           DBMS_OUTPUT.PUT_LINE(substr('    Text:' ||mail_pkg.mailbox(i).message,1,255) );         
           DBMS_OUTPUT.PUT_LINE('    Attachments:' ||mail_pkg.mailbox(i).attachments.count);

           IF mail_pkg.mailbox(i).attachments.count>0 THEN
             FOR att IN 1..mail_pkg.mailbox(i).attachments.count LOOP
               -- Real Attachments 
               IF mail_pkg.mailbox(i).attachments(att).hdr.exists('Content-Disposition') 
                 AND INSTR(mail_pkg.mailbox(i).attachments(att).hdr('Content-Disposition'),'attachment')>0               
               THEN
                 DBMS_OUTPUT.PUT_LINE('    filename: '
                    ||mail_pkg.extract_value(mail_pkg.mailbox(i).attachments(att).hdr('Content-Disposition'),'filename')
                    ||', about '||trunc(dbms_lob.getlength(mail_pkg.mailbox(i).attachments(att).content)/1024) ||'Kbytes'                 
                   );
                 -- You can convert this CLOB into BLOB ans save it into database or as file  
                 -- mail_pkg.mailbox(i).attachments(att).content                   
                                    
               END IF; 
               -- Preview includes and text-attachments 
               IF  mail_pkg.mailbox(i).attachments(att).hdr.exists('Content-Type') THEN
                 IF  INSTR(mail_pkg.mailbox(i).attachments(att).hdr('Content-Type'),'text')>0 THEN
                   DBMS_OUTPUT.PUT_LINE(substr('    PreviewAttachmentText:' ||mail_pkg.mailbox(i).attachments(att).content,1,255) );             
                 END IF;
               END IF;  
             END LOOP;
           END IF;                           
         END IF;     
       END LOOP;
   
       MAIL_PKG.MAIL_DISCONNECT;
    EXCEPTION WHEN OTHERS THEN
      -- ANYCASE YOU MUST CLOSE CONNECTION
      MAIL_PKG.MAIL_DISCONNECT;
    END;       
*/

 POP3 CONSTANT VARCHAR2(4):='POP3';
 SMTP CONSTANT VARCHAR2(4):='SMTP';
 IMAP CONSTANT VARCHAR2(4):='IMAP';

 DEBUG_ALL CONSTANT INT := 0;
 DEBUG_MESSAGES CONSTANT INT := 1;
 DEBUG_WARNINGS CONSTANT INT := 2;
 DEBUG_ERRORS CONSTANT INT := 3; 

 DEBUG BOOLEAN := FALSE;
 DEBUG_LEVEL NUMBER := DEBUG_WARNINGS;

 -- SET_MAILSERVER:
 --  Set up mail server for send emails. Default Localhost
 -- IN
 -- MAILSERVER is ip or url of mail server
 -- MAILPORT is port for mail server. Default 25
 PROCEDURE SET_MAILSERVER ( mailserver varchar2
                          , mailport number default 25
                          );

 -- SET_AUTH
 --  Set authorization on smtp server
 -- IN
 -- AUTH_USER is authorization user
 -- AUTH_PASS is password for AUTH_USER
 --
 -- Execute SET_AUTH(); -- for disable authorization
 PROCEDURE SET_AUTH (  auth_user varchar2 default null
                     , auth_pass varchar2 default null
                          );

 -- ENCODE:
 --  Encodes string to email compatible view
 -- IN
 -- STR is string to convert
 -- TP is type of convert:
 --    B - is base64 encoding
 FUNCTION ENCODE( str IN VARCHAR2
                , tp IN VARCHAR2 DEFAULT 'Q') RETURN VARCHAR2;

 -- PREPARE
 --  Prepare configs for email.
 PROCEDURE PREPARE;

 -- ADD_RCPT
 --  Add recipient to recipients list exploded by  ','
 -- STR is variable with recipients
 -- RCPTMAIL is recipient mail added to STR
 -- RCPTNAME is recipient name added to STR
 -- Example: str='user1@domain.ru' rcptmail='user2@domain.ru'
 --  after => str='user1@domain.ru, user2@domain.ru'
 PROCEDURE ADD_RCPT( str IN OUT VARCHAR2
                   , rcptmail IN VARCHAR2
				   , rcptname IN VARCHAR2 DEFAULT NULL);

 -- ADD_ATTACHMENT
 --  Add file-attachment to attachments list to email
 -- IN
 -- DIRNAME is logical link to access physical directories of server. See DBA_DIRECTORIES table
 -- FILENAME is name of file to attach
 -- MIMETYPE is mime-type for sended file
 -- NAME is name for attached file for email. Default eq FILENAME
 PROCEDURE ADD_ATTACHMENT ( dirname IN varchar2
                          , filename IN varchar2
						  , mimetype IN varchar2 DEFAULT 'text/plain'
                          , name IN varchar2 DEFAULT NULL
                           );
 -- ADD_ATTACHMENT
 --  Add blob-attachment to attachments list to email
 -- IN
 -- BLOBLOC - Blob locator for attached blob
 -- FILENAME is name of file to attach
 -- MIMETYPE is mime-type for sended file
 PROCEDURE ADD_ATTACHMENT ( blobloc IN blob
                          , filename IN varchar2
						  , mimetype IN varchar2 DEFAULT 'text/html'
                           );
						   
 -- SEND
 --  Send email with attachments to recipient
 -- IN
 -- MAILTO is name and email addresses of recipients ( ex. "user@domain.com"
 --       , "User Name <user@domain.com>", "User1 <user1@domain>, User2 <user2@domain>")
 -- SUBJECT is subject of email
 -- MESSAGE is message of email
 -- MAILFROM is name and email of sender. (ex. "no-reply@domain", "Notify system <no-reply@domain>")
 -- MIMETYPE is mime-type of message. Available values is 'text/plain' and 'text/html'
 -- PRIORITY is priority of mail (1 - High, 2 - Highest, 3 - Normal, 4 - Lowest, 5 - Low)
 PROCEDURE SEND ( mailto IN VARCHAR2
				, subject IN VARCHAR2
				, message IN CLOB
                , mailfrom IN VARCHAR2 DEFAULT NULL
				, mimetype IN VARCHAR2 DEFAULT 'text/plain'
				, priority IN NUMBER DEFAULT NULL
                );

 FUNCTION DECODE_CHARSET (str IN VARCHAR2, charset varchar2) RETURN VARCHAR2;
 
 FUNCTION MIME_DECODE(str IN VARCHAR2) RETURN VARCHAR2;

 FUNCTION extract_value(str IN VARCHAR2,entity IN VARCHAR2) RETURN VARCHAR2;

 TYPE T_HDR IS TABLE OF VARCHAR2(32717) INDEX BY VARCHAR2(2555);				
 
 TYPE T_ATTACHMENT IS RECORD ( boundary varchar2(255)
                          , ContentTransferEncoding varchar2(25)
                          , charset varchar2(25)
                          , hdr t_hdr
                          , content clob
                           );
 
 TYPE T_ATTACHMENTS IS TABLE OF T_ATTACHMENT;

 TYPE MESSAGE IS RECORD( hdr              t_hdr
                        ,MailFrom         varchar2(32717)
                        ,MailTo           varchar2(32717)
                        ,ReturnPath       varchar2(32717)
                        ,Subject          varchar2(32717)
                        ,MailDate         DATE
                        ,message          CLOB
                        ,bytes            number
                        ,ContentTransferEncoding varchar2(25)
                        ,charset          varchar2(25)
                        ,attachments         t_attachments := t_attachments()                                                                         
                       );			
					   
 TYPE MAILBOXT IS TABLE OF MESSAGE INDEX BY PLS_INTEGER;				
 MAILBOX MAILBOXT;			
 	
 FUNCTION PARSE_LINE (line varchar2, ContentTransferEncoding varchar2, charset varchar2 default null) RETURN varchar2; 
  
 PROCEDURE MAIL_CONNECT;
 
 PROCEDURE MAIL_DISCONNECT;
 			
 PROCEDURE GET_HEADERS;		

 PROCEDURE GET_MAIL(mail_id number,lines number default null);	
 
 PROCEDURE DELETE_MAIL(mail_id number);	
 
END MAIL_PKG;
/

CREATE OR REPLACE PACKAGE BODY MAIL_PKG
IS

 mailserver VARCHAR2(30):='localhost';
 mailport INTEGER:=25;
 auth_user VARCHAR2(50);
 auth_pass VARCHAR2(50);
 crlf         VARCHAR2(2)  := utl_tcp.CRLF; -- chr(13)||chr(10);

 c  utl_tcp.connection;  -- TCP/IP connection to the Web server (for pop3)

 type attach_row is record ( dirname varchar2(30)
                           , filename  varchar2(30)
                           , name  varchar2(30)
						   , mimetype varchar2(30)
						   , blobloc blob
						   , attachtype varchar2(30)
                           );
 type attach_list is table of attach_row;
 attachments attach_list;

 type rcpt_row is record ( rcptname varchar2(100)
                     , rcptmail varchar2(50)
					 );
 type rcpt_list is table of rcpt_row;

 PROCEDURE SET_MAILSERVER ( mailserver varchar2
                          , mailport number default 25
                          ) IS
 BEGIN
  MAIL_PKG.mailserver := mailserver;
  MAIL_PKG.mailport := mailport;
 END;

 PROCEDURE SET_AUTH (  auth_user varchar2 default null
                     , auth_pass varchar2 default null
                          ) IS
 BEGIN
   MAIL_PKG.auth_user := auth_user;
   MAIL_PKG.auth_pass := auth_pass;
 END;

 FUNCTION ENCODE(str IN VARCHAR2, tp IN VARCHAR2 DEFAULT 'Q') RETURN VARCHAR2 IS
 BEGIN
   -- ToDo: UTL_ENCODE.QUOTED_PRINTABLE | UTL_ENCODE.BASE64
   IF tp='B' THEN
     RETURN '=?utf-8?b?'|| UTL_RAW.cast_to_varchar2(UTL_ENCODE.base64_encode(UTL_RAW.cast_to_raw (CONVERT (SUBSTR(str,1,24), 'UTF8'))))|| '?='
	     || CASE WHEN SUBSTR(str,25) IS NOT NULL THEN crlf || ' '|| ENCODE(SUBSTR(str,25),tp) END;
   ELSIF tp='Q' THEN
     RETURN '=?utf-8?q?' || UTL_RAW.cast_to_varchar2(utl_encode.QUOTED_PRINTABLE_ENCODE(utl_raw.cast_to_raw(CONVERT (SUBSTR(str,1,8), 'UTF8') ))) || '?='
	     || CASE WHEN SUBSTR(str,9) IS NOT NULL THEN crlf || ' '|| ENCODE(SUBSTR(str,9),tp) END;
   ELSE
     RETURN str;
   END IF;
 END;
 
 FUNCTION DECODE_CHARSET (str IN VARCHAR2, charset varchar2) RETURN VARCHAR2 IS
 BEGIN
   return CONVERT(str,SUBSTR(USERENV ('language'),INSTR(USERENV ('language'),'.')+1)
                   , CASE lower(charset) WHEN 'koi8-r' THEN 'CL8KOI8R'
                                  WHEN 'utf-8' THEN 'UTF8'
                     ELSE SUBSTR(USERENV ('language'),INSTR(USERENV ('language'),'.')+1)
                     END
                   );
 END;
 
 FUNCTION MIME_DECODE(str IN VARCHAR2) RETURN VARCHAR2 IS
   strout VARCHAR2(32717);
  buff varchar2(32717);
 text varchar2(32717);
 encode_method varchar2(1);
 charset varchar2(25);
BEGIN
  strout := str;
  LOOP
    IF instr(strout,'=?')>0 and instr(strout,'?=')>0 and instr(strout,'?=') > instr(strout,'=?') then
      buff := substr(substr(strout,instr(strout,'=?')),1,1+instr(substr(strout,instr(strout,'=?')),'?=',instr(substr(strout,instr(strout,'=?')),'?',1,3)+1 ));      
      charset := lower(substr(buff,3, instr(substr(buff,3),'?')-1));
      encode_method := substr(buff, 4+length(charset),1);
      text := substr(buff,instr(buff,'?',1,3)+1, instr(buff,'?',1,4)-instr(buff,'?',1,3)-1);
      IF  encode_method = 'B' THEN
       text := UTL_RAW.cast_to_varchar2(UTL_ENCODE.base64_decode(UTL_RAW.cast_to_raw(text)));
      ELSE
       text := UTL_RAW.cast_to_varchar2(utl_encode.quoted_printable_decode(UTL_RAW.cast_to_raw(replace(text,'_',' '))));   
      END IF;
      text := DECODE_CHARSET(text,charset); 
      strout:=REPLACE(strout,buff,text);                   
    ELSE
       EXIT;                
    END IF;
  END LOOP;      
    RETURN strout;
 END;

 PROCEDURE extract_value(val IN OUT varchar2, str IN VARCHAR2,entity IN VARCHAR2) 
 IS
  buff varchar2(255);
  returnval varchar2(255);
 BEGIN
    if instr(str,entity)=0 
    then
     return;
    else
     val := replace(substr(str,length(entity)+1+instr(str,entity||'='), instr(substr(str||';',length(entity)+1+instr(str,entity||'=')),';')-1),'"','');
    end if;
 END;

 FUNCTION extract_value(str IN VARCHAR2,entity IN VARCHAR2) RETURN VARCHAR2 IS
  p_val varchar2(32717):='';
 BEGIN
   mail_pkg.extract_value(p_val ,str ,entity );
   return p_val; 
 END;


 PROCEDURE PREPARE
 IS
 BEGIN
   MAIL_PKG.attachments:=MAIL_PKG.attach_list();
 END;

 PROCEDURE ADD_RCPT( str IN OUT VARCHAR2
                   , rcptmail IN VARCHAR2
				   , rcptname IN VARCHAR2 DEFAULT NULL) IS
  rcpt varchar2(255);
 BEGIN
  rcpt:=CASE WHEN rcptname is null THEN
          ' <'|| rcptmail ||'>' --rcptmail
		ELSE
		  trim(replace(replace(rcptname,',',' '),';',' '))||' <'|| rcptmail ||'>'
		END;
  IF trim(str) is NULL THEN
     str :=  trim(rcpt);
  ELSE
     str := str||', '||trim(rcpt);
  END IF;
 END;

 PROCEDURE ADD_ATTACHMENT ( dirname IN varchar2
                          , filename IN varchar2
						  , mimetype IN varchar2 DEFAULT 'text/plain'
                          , name IN varchar2 DEFAULT NULL
                           )
 IS
  v_fl BFILE :=BFILENAME(dirname,filename);
 BEGIN
   IF DBMS_LOB.FILEEXISTS (v_fl)=1 THEN
      MAIL_PKG.attachments.extend;
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).dirname:=dirname;
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).filename:=filename;
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).name:=nvl(name,filename);
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).mimetype:=mimetype;
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).attachtype:='FILE';	  
   ELSE
      RAISE_APPLICATION_ERROR(-20001, 'File is not exists');
   END IF;
 END;
 
 PROCEDURE ADD_ATTACHMENT ( blobloc IN blob
                          , filename IN varchar2
						  , mimetype IN varchar2 DEFAULT 'text/html'
                           )
 IS 
 BEGIN
      MAIL_PKG.attachments.extend;
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).name:=filename;
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).mimetype:=mimetype;
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).blobloc:=blobloc;	  
      MAIL_PKG.attachments(MAIL_PKG.attachments.count).attachtype:='BLOB';	  
 END; 						   
 

 FUNCTION CREATE_RCPT_LIST(mailto IN VARCHAR2) RETURN MAIL_PKG.rcpt_list IS
  v_mailto VARCHAR2(4096) := replace(mailto,';',',')||',';
  pntr INTEGER;
  buf VARCHAR2(255);
  rcptmail VARCHAR2(255);
  rcptlist MAIL_PKG.rcpt_list:=MAIL_PKG.rcpt_list();
 BEGIN
  FOR maxrcptnts IN 1..50
  LOOP
     pntr:=INSTR(v_mailto,','); buf := substr(v_mailto,1,pntr-1);
     IF pntr>0 THEN
	   IF INSTR(buf,'<')>0 AND INSTR(buf,'>')>0 THEN
	     rcptmail:= SUBSTR(buf,INSTR(buf,'<')+1,INSTR(SUBSTR(buf,INSTR(buf,'<')+1),'>')-1);
		 IF rcptmail IS NOT NULL THEN
	        rcptlist.extend;
		    rcptlist(rcptlist.count).rcptmail := TRIM(rcptmail);
		    rcptlist(rcptlist.count).rcptname := TRIM(SUBSTR(buf,1,INSTR(buf,'<')-1));
	     END IF;
       ELSE
	     rcptmail := TRIM(buf);
		 IF rcptmail IS NOT NULL THEN
           rcptlist.extend;
		   rcptlist(rcptlist.count).rcptmail:= TRIM(rcptmail);
		 END IF;
	   END IF;
	 ELSE
	   EXIT;
	 END IF;
	 v_mailto := substr(v_mailto,pntr+1);
   END LOOP;
   RETURN rcptlist;
 END;

 PROCEDURE SEND ( mailto IN VARCHAR2
				, subject IN VARCHAR2
				, message IN CLOB
                , mailfrom IN VARCHAR2 DEFAULT NULL
				, mimetype IN VARCHAR2 DEFAULT 'text/plain'
				, priority IN NUMBER DEFAULT NULL
                )
 IS
   v_Mail_Conn  utl_smtp.Connection;
   boundary VARCHAR2(50) := '-----7D81B75CCC90DFRW4F7A1CBD';
   vFile BFILE;
   vRAW RAW(32767);
   amt CONSTANT BINARY_INTEGER := 10368; -- 48bytes binary convert to 128bytes of base64. (32767/2 max for raw convert)
   v_amt BINARY_INTEGER;
   ps BINARY_INTEGER := 1;
   message_part varchar2(32767);
   v_mime VARCHAR2(30);
   reply UTL_SMTP.REPLY;
   replies UTL_SMTP.REPLIES;
   rcptlist MAIL_PKG.rcpt_list;
   sndr MAIL_PKG.rcpt_row;
 BEGIN
    rcptlist:=create_rcpt_list(mailto);
	IF rcptlist.count=0 THEN
      RAISE_APPLICATION_ERROR(-20001, 'Recipients requered');
	END IF;
    IF mimetype<>'text/html' and mimetype<>'text/plain' THEN
      RAISE_APPLICATION_ERROR(-20001, 'MimeType must be "text/html" or "text/plain"');
    ELSE
      v_mime:=mimetype;
    END IF;
    v_Mail_Conn := utl_smtp.Open_Connection(MAIL_PKG.mailserver, MAIL_PKG.mailport);
    replies:=utl_smtp.Ehlo(v_Mail_Conn,MAIL_PKG.mailserver);
	if create_rcpt_list(mailfrom).count>0 then
	  sndr := create_rcpt_list(mailfrom)(1);
	else
	  sndr := create_rcpt_list( 'mail@' || UTL_INADDR.GET_HOST_NAME )(1); -- host from oracle-server
	  -- sndr := create_rcpt_list( 'mail@' || substr(replies(1).text,1,instr(replies(1).text,' ')-1))(1); -- Addr from ehlo answer
    end if;

    if mail_pkg.auth_user is not null then
       for x IN 1 .. replies.count loop
 	     IF INSTR(replies(x).text,'AUTH')>0 then -- If server supply authorization
            utl_smtp.command(v_Mail_Conn, 'AUTH LOGIN');
            utl_smtp.command(v_Mail_Conn,utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(auth_user))));
            utl_smtp.command(v_Mail_Conn,utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(auth_pass))));
			exit;
		 END IF;
	   end loop;
    end if;

    utl_smtp.Mail(v_Mail_Conn, sndr.rcptmail);
    FOR rcpts IN 1 .. rcptlist.count
	LOOP
	  utl_smtp.Rcpt(v_Mail_Conn, rcptlist(rcpts).rcptmail);
	END LOOP;

    utl_smtp.open_data(v_Mail_Conn); -- open data sheet
    utl_smtp.write_data(v_Mail_Conn, 'Date: ' || TO_CHAR(SYSTIMESTAMP,'Dy, DD Mon YYYY HH24:MI:SS TZHTZM','NLS_DATE_LANGUAGE = ''american''') || crlf);
    utl_smtp.write_data(v_Mail_Conn, 'From: ');
	if sndr.rcptname is not null then
        utl_smtp.write_data(v_Mail_Conn, MAIL_PKG.ENCODE(sndr.rcptname) ||' <'|| sndr.rcptmail || '>');
	else
        utl_smtp.write_data(v_Mail_Conn, sndr.rcptmail);
	end if;
    utl_smtp.write_data(v_Mail_Conn, crlf );
    utl_smtp.write_data(v_Mail_Conn, 'Subject: '|| MAIL_PKG.ENCODE(subject) || crlf );
    utl_smtp.write_data(v_Mail_Conn, 'To: ');
    FOR rcpts IN 1 .. rcptlist.count
	LOOP
	  if rcpts>1 then
       utl_smtp.write_data(v_Mail_Conn, ',');
	  end if;
	  if rcptlist(rcpts).rcptname is not null then
        utl_smtp.write_data(v_Mail_Conn, MAIL_PKG.ENCODE(rcptlist(rcpts).rcptname) ||' <'|| rcptlist(rcpts).rcptmail || '>');
	  else
        utl_smtp.write_data(v_Mail_Conn, rcptlist(rcpts).rcptmail);
	  end if;
	END LOOP;
    utl_smtp.write_data(v_Mail_Conn, crlf );

	IF priority IS NOT NULL and priority BETWEEN 1 AND 5 THEN
      utl_smtp.write_data(v_Mail_Conn, 'X-Priority: ' || priority || crlf );
	END IF;
    utl_smtp.write_data(v_Mail_Conn, 'MIME-version: 1.0' || crlf );
    utl_smtp.write_data(v_Mail_Conn, 'Content-Type: multipart/mixed;'|| crlf );
    utl_smtp.write_data(v_Mail_Conn, ' boundary="'||boundary||'"'|| crlf );
    utl_smtp.write_data(v_Mail_Conn, crlf );
 
    --Message
	IF message IS NOT NULL THEN	
    utl_smtp.write_data(v_Mail_Conn, '--'|| boundary || crlf );
    utl_smtp.write_data(v_Mail_Conn, 'Content-Type: '||v_mime||'; charset="utf-8"'|| crlf );
    utl_smtp.write_data(v_Mail_Conn, 'Content-Transfer-Encoding: 8bit'|| crlf );
    utl_smtp.write_data(v_Mail_Conn, crlf );
    -- utl_smtp.write_raw_data(v_Mail_Conn, utl_raw.cast_to_raw(CONVERT(message,'UTF8')));
    ps:=1; v_amt:=amt;
    LOOP
      BEGIN
        dbms_lob.read(message, v_amt, ps, message_part);
        ps := ps + v_amt;
        utl_smtp.write_raw_data(v_Mail_Conn, utl_raw.cast_to_raw(CONVERT(message_part,'UTF8')));                 
      EXCEPTION
        WHEN no_data_found THEN
             EXIT;
      END;            
    END LOOP; 
    utl_smtp.write_data(v_Mail_Conn, crlf );
    utl_smtp.write_data(v_Mail_Conn, crlf );
    END IF;
	
	--Attachments
	IF MAIL_PKG.attachments.count>0 THEN
	  FOR x IN 1 .. MAIL_PKG.attachments.count LOOP
          utl_smtp.write_data(v_Mail_Conn, '--'|| boundary || crlf );
		  -- HOTFIX
		  IF message IS NOT NULL OR x!=1 THEN
            utl_smtp.write_data(v_Mail_Conn, 'Content-Type: '||MAIL_PKG.attachments(x).mimetype||';'|| crlf );
            utl_smtp.write_data(v_Mail_Conn, ' name="');
	        utl_smtp.write_raw_data(v_Mail_Conn,utl_raw.cast_to_raw(MAIL_PKG.attachments(x).name));
            utl_smtp.write_data(v_Mail_Conn, '"' || crlf);
            utl_smtp.write_data(v_Mail_Conn, 'Content-Transfer-Encoding: base64'|| crlf );
            utl_smtp.write_data(v_Mail_Conn, 'Content-Disposition: attachment;'|| crlf );
            utl_smtp.write_data(v_Mail_Conn, ' filename="' || MAIL_PKG.ENCODE(MAIL_PKG.attachments(x).name) || '"' || crlf);
		  ELSE
           utl_smtp.write_data(v_Mail_Conn, 'Content-Type: '||MAIL_PKG.attachments(x).mimetype||'; charset="utf-8"'|| crlf );
           utl_smtp.write_data(v_Mail_Conn, 'Content-Transfer-Encoding: base64'|| crlf );
          END IF;			
          utl_smtp.write_data(v_Mail_Conn, crlf );
		  IF MAIL_PKG.attachments(x).attachtype = 'FILE' THEN 
             vFile := BFILENAME(MAIL_PKG.attachments(x).dirname,MAIL_PKG.attachments(x).filename);
		     dbms_lob.fileopen(vFile, dbms_lob.file_readonly);
             ps:=1; v_amt:=amt;
		     LOOP
		       BEGIN
		         dbms_lob.read (vFile, v_amt, ps, vRAW);
			     ps := ps + v_amt;
                 utl_smtp.write_raw_data(v_Mail_Conn, UTL_ENCODE.base64_encode(vRAW));
		       EXCEPTION
                 WHEN no_data_found THEN
			       EXIT;
			   END;			
		     END LOOP;
		     dbms_lob.fileclose(vFile);
		  ELSIF MAIL_PKG.attachments(x).attachtype = 'BLOB' THEN
		  	 dbms_lob.open(MAIL_PKG.attachments(x).blobloc, dbms_lob.file_readonly);
             ps:=1; v_amt:=amt;
		     LOOP
		       BEGIN
		         dbms_lob.read (MAIL_PKG.attachments(x).blobloc, v_amt, ps, vRAW);
			     ps := ps + v_amt;
                 utl_smtp.write_raw_data(v_Mail_Conn, UTL_ENCODE.base64_encode(vRAW));
		       EXCEPTION
                 WHEN no_data_found THEN
			       EXIT;
			   END;			
		     END LOOP;
		     dbms_lob.close(MAIL_PKG.attachments(x).blobloc);					  	 
		  END IF;		 		  

          utl_smtp.write_data(v_Mail_Conn, crlf );
          utl_smtp.write_data(v_Mail_Conn, crlf );
	  END LOOP;
	END IF;

    -- Final Boundary
    utl_smtp.write_data(v_Mail_Conn, '--' || boundary || '--');

    utl_smtp.close_data(v_Mail_Conn);
    utl_smtp.quit(v_Mail_Conn);

	-- Clear attachments
    MAIL_PKG.attachments:=MAIL_PKG.attach_list();

 EXCEPTION
    WHEN OTHERS THEN
       BEGIN
         MAIL_PKG.attachments:=MAIL_PKG.attach_list();
		 utl_smtp.rset(v_Mail_Conn);
	     utl_smtp.quit(v_Mail_Conn);
	   EXCEPTION WHEN OTHERS THEN NULL;
	   END;
	RAISE;
 END;

 PROCEDURE PDEBUG(mess IN varchar2, plevel IN NUMBER DEFAULT 0) IS
 BEGIN
   IF MAIL_PKG.DEBUG AND plevel>=MAIL_PKG.DEBUG_LEVEL THEN
     dbms_output.put_line(substr(mess,1,255));
   END IF;
 END;

 PROCEDURE CMD(c in out utl_tcp.connection, command in varchar2,status out varchar2, answer out varchar2) is
   ret_val pls_integer; 
--   pc 
   answr varchar2(32767); 
 begin
   ret_val := utl_tcp.write_line(c,command);
   answr := utl_tcp.get_line(c, TRUE);
   status := trim(substr(answr,1,instr(answr,' ')));
   answer := substr(answr,instr(answr,' ')+1);
   if mail_pkg.debug then
    PDEBUG('DEBUG:'||status||' '||answer,mail_pkg.debug_messages);
   end if;
   if status = '-ERR' then
     raise_application_error (-20000,answr);
   end if;
 end;
 
 FUNCTION PARSE_LINE (line varchar2, ContentTransferEncoding varchar2, charset varchar2 default null) RETURN varchar2 IS
  decoding_line varchar2(255);
 BEGIN
   decoding_line := line;
   IF decoding_line is null then return null; END IF;
   IF ContentTransferEncoding = 'base64' then
      decoding_line := UTL_RAW.cast_to_varchar2(UTL_ENCODE.base64_decode(UTL_RAW.cast_to_raw(decoding_line)));
   ELSIF ContentTransferEncoding = 'quoted-printable' then
      decoding_line := UTL_RAW.cast_to_varchar2(UTL_ENCODE.quoted_printable_decode(UTL_RAW.cast_to_raw(decoding_line)));   
   END IF;   
   decoding_line := DECODE_CHARSET(decoding_line,charset);
   
   RETURN decoding_line;
 EXCEPTION WHEN OTHERS THEN
   PDEBUG('ERR: PARSE:' || ContentTransferEncoding || ' ' || charset || ',' || line || ' > '||decoding_line, mail_pkg.debug_errors);
   RETURN NULL;   
 END;
 
 
 PROCEDURE MAIL_CONNECT IS
  p_ip varchar2(25);
  answer varchar2(32767);
  status varchar2(25);
  cnt number;
  bytes number;         
 BEGIN
  p_ip := UTL_INADDR.GET_HOST_ADDRESS(mailserver);
  c := utl_tcp.open_connection(remote_host => p_ip,
                               remote_port =>  110,
                               charset     => 'US7ASCII',
                               tx_timeout => 10);  -- open connection
  answer := utl_tcp.get_line(c, TRUE); 
  PDEBUG(answer,mail_pkg.debug_messages);  -- read result
  CMD(c,'USER '||MAIL_PKG.auth_user,status,answer);  
  CMD(c,'PASS '||MAIL_PKG.auth_pass,status,answer);
 BEGIN
  CMD(c,'STAT',status,answer);
  cnt := to_number(trim(substr(answer,1,instr(answer,' '))));
  bytes := to_number(trim(substr(answer,instr(answer,' ')))); 
  -- INIT ARRAY
  MAILBOX.DELETE;
  FOR mail_id IN 1 .. cnt  
  LOOP
       MAILBOX(mail_id).bytes := 0;        
  END LOOP;
 END;
    
 END;
 
 PROCEDURE MAIL_DISCONNECT IS
  answer varchar2(32767); 
  status varchar2(25); 
 BEGIN
   CMD(c,'QUIT',status,answer);  
   utl_tcp.close_connection(c);
 EXCEPTION WHEN OTHERS THEN
  BEGIN   
    utl_tcp.close_connection(c);
  EXCEPTION WHEN OTHERS THEN NULL;
  END;    
  RAISE;
 END;

 PROCEDURE GET_HEADERS IS 
  answer varchar2(32767);
  status varchar2(25);  
  cnt number;
  bytes number;     
 BEGIN
  CMD(c,'STAT',status,answer);
  cnt := to_number(trim(substr(answer,1,instr(answer,' '))));
  bytes := to_number(trim(substr(answer,instr(answer,' ')))); 
  -- GET MESSAGE SUBJECTS
  FOR mail_id IN 1 .. cnt -- cnt --1 ..  cnt 
  LOOP
       GET_MAIL(mail_id,0);   -- ,0 !!!!!        
  END LOOP;
 END;

 
 PROCEDURE GET_MAIL(mail_id number,lines number default null) IS
  answer varchar2(32767);
  cnt number;
  bytes number;
  status varchar2(25);
  message_body clob;
  hdr_flag boolean;
  hdr_entity varchar2(255);
  hdr_entity_value varchar2(32717);  
  boundary varchar2(128);
  part_header_flag boolean:=false;
  any_boundary_found boolean:=false;
  any_boundary_found_close boolean:=false;
 BEGIN     
 
       CMD(c,'LIST '||mail_id,status,answer); -- get message size
       MAILBOX(mail_id).bytes:=to_number(trim(substr(answer,instr(answer,' '))));

       IF  MAILBOX(mail_id).bytes >= 1048576 THEN             
           PDEBUG('BUG: Message '|| mail_id ||' over 1Mb, ' ||  MAILBOX(mail_id).bytes || ' bytes' ,mail_pkg.debug_errors);
       END IF;
       
       CMD(c,CASE WHEN lines is NULL THEN 'RETR '||mail_id ELSE 'TOP '||mail_id||' 10' END,status,answer); -- read message headers
       BEGIN
         hdr_entity:='';hdr_entity_value:=''; 
         hdr_flag := true;
         if lines<>0 or lines is null then
            MAILBOX(mail_id).message:='';
            MAILBOX(mail_id).attachments := t_attachments();            
         end if;
         dbms_lob.createtemporary(lob_loc => MAILBOX(mail_id).message, cache => true, dur => dbms_lob.call);                                  
         LOOP
             answer :=utl_tcp.get_line(c, TRUE);  -- read result
             EXIT WHEN answer = '.';             
             IF answer IS NULL THEN hdr_flag := false; END IF;
             IF hdr_flag THEN
                 IF ascii(substr(answer,0,1)) NOT IN (9,32) THEN
                   hdr_entity := substr(answer,1,instr(answer,':')-1);
                   MAILBOX(mail_id).HDR(hdr_entity):='';                                    
                   hdr_entity_value := substr(answer,instr(answer,':')+2);
                 ELSE 
                   hdr_entity_value := answer;  
                 END IF;

                 PDEBUG('HDR:'|| answer);              
                 MAILBOX(mail_id).HDR(hdr_entity):= MAILBOX(mail_id).HDR(hdr_entity)
                                                 || MIME_DECODE(hdr_entity_value);  
                 IF hdr_entity = 'Content-Type' THEN
                   if instr(answer,'boundary="')>0 then
                      extract_value(boundary,answer,'boundary');                   
                   end if;                 
                 END IF;                                                                                                              
             ELSE   
                 any_boundary_found := false;
                 any_boundary_found_close := false;                 
                 IF MAILBOX(mail_id).attachments.count>0 THEN
                 FOR incls IN MAILBOX(mail_id).attachments.first .. MAILBOX(mail_id).attachments.last
                 LOOP 
                   if answer = '--' || MAILBOX(mail_id).attachments(incls).boundary then
                     any_boundary_found := true;
                   end if;
                   if answer = '--' || MAILBOX(mail_id).attachments(incls).boundary || '--' then
                     any_boundary_found_close := true;
                   end if;                   
                 END LOOP;
                 END IF;
                 
                 if boundary is not null and 
                    ( answer = '--' || boundary 
                      or
                      any_boundary_found
                    )
                     then
                    part_header_flag:=true;
                    MAILBOX(mail_id).attachments.extend();
                    dbms_lob.createtemporary(lob_loc => MAILBOX(mail_id).attachments(MAILBOX(mail_id).attachments.last).content, cache => true, dur => dbms_lob.call);  
                 elsif boundary is not null and 
                   (  answer = '--' || boundary || '--'
                     or 
                     any_boundary_found_close
                   )
                     then
                       null;                   
                 elsif part_header_flag and answer is null then
                    part_header_flag:=false;
                 else
                    IF part_header_flag THEN
                       IF ascii(substr(answer,0,1)) NOT IN (9,32) THEN
                          hdr_entity := substr(answer,1,instr(answer,':')-1);
                          MAILBOX(mail_id).attachments(MAILBOX(mail_id).attachments.last).HDR(hdr_entity):='';                                    
                          hdr_entity_value := substr(answer,instr(answer,':')+2);
                       ELSE 
                          hdr_entity_value := answer;  
                       END IF;
                       MAILBOX(mail_id).attachments(MAILBOX(mail_id).attachments.last).HDR(hdr_entity):= 
                              MAILBOX(mail_id).attachments(MAILBOX(mail_id).attachments.last).HDR(hdr_entity)
                           || MIME_DECODE(hdr_entity_value);
                       
                       IF hdr_entity = 'Content-Type' THEN
                          extract_value(MAILBOX(mail_id).attachments(MAILBOX(mail_id).attachments.last).boundary,answer,'boundary');                       
                          extract_value(MAILBOX(mail_id).attachments(MAILBOX(mail_id).attachments.last).charset,answer,'charset');
--                            PDEBUG(MAILBOX(mail_id).includes(MAILBOX(mail_id).includes.last).charset,mail_pkg.debug_messages);                                           
                       ELSIF hdr_entity = 'Content-Transfer-Encoding' THEN
                            MAILBOX(mail_id).attachments(MAILBOX(mail_id).attachments.last).ContentTransferEncoding := hdr_entity_value;                         
                       END IF;                                                                                                              
                                                                             
                    ELSE 
                    
                       -- BUG: BIG messages is very slow and prc can get "[SYS/PERM] Fatal error: Lost connection to input stream"
                       IF MAILBOX(mail_id).bytes < 1048576 THEN 
                         IF MAILBOX(mail_id).attachments.count>0 THEN
                            IF length(answer)>0 THEN
                              DBMS_LOB.APPEND ( MAILBOX(mail_id).attachments(MAILBOX(mail_id).attachments.last).content 
                              , PARSE_LINE( answer
                                           ,MAILBOX(mail_id).attachments(MAILBOX(mail_id).attachments.last).ContentTransferEncoding
                                           ,MAILBOX(mail_id).attachments(MAILBOX(mail_id).attachments.last).charset)  
                              );
                            END IF;                         
                         ELSE 
                            IF length(answer)>0 THEN
                              DBMS_LOB.APPEND ( MAILBOX(mail_id).message  
                              , --PARSE_LINE( 
                                            answer
                                  --         ,ContentTransferEncoding
                                    --       ,charset)                                
                              );
                            END IF;                         
                         END IF;
                       END IF;
                                  
                    END IF;                  
                    PDEBUG(CASE part_header_flag WHEN TRUE THEN 'H' ELSE 'B' END || '-BODY:'||answer);                                   
                 end if;   
             END IF;
                        
         END LOOP;
       EXCEPTION
         WHEN OTHERS THEN 
         PDEBUG('ERR: GET MESSAGE ' ||mail_id || ' ERROR ',mail_pkg.debug_errors);         
         RAISE;
       END;
       IF MAILBOX(mail_id).HDR.EXISTS('From') THEN
          MAILBOX(mail_id).MailFrom := MAILBOX(mail_id).HDR('From');
       END IF;   
       IF MAILBOX(mail_id).HDR.EXISTS('MailTo') THEN
          MAILBOX(mail_id).MailTo := MAILBOX(mail_id).HDR('To');
       END IF;   
       IF MAILBOX(mail_id).HDR.EXISTS('Return-Path') THEN
          MAILBOX(mail_id).ReturnPath := MAILBOX(mail_id).HDR('Return-Path');
       END IF;
       IF MAILBOX(mail_id).HDR.EXISTS('Subject') THEN
          MAILBOX(mail_id).Subject := MAILBOX(mail_id).HDR('Subject');
       END IF;   
       IF MAILBOX(mail_id).HDR.EXISTS('Date') THEN
          BEGIN
            MAILBOX(mail_id).MailDate := TO_TIMESTAMP_TZ(MAILBOX(mail_id).HDR('Date'),'Dy, DD Mon YYYY HH24:MI:SS TZHTZM','NLS_DATE_LANGUAGE = ''american''');
          EXCEPTION WHEN OTHERS THEN NULL; END;   
       END IF;     
 END;
 
 PROCEDURE DELETE_MAIL(mail_id number) IS
  answer varchar2(32767);
  status varchar2(25);  
 BEGIN
   CMD(c,'DELE '||mail_id,status,answer); 
 END;  
    
BEGIN
  MAIL_PKG.attachments:=MAIL_PKG.attach_list();
END;
/
17 сен 12, 13:43    [13175640]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
-2-
Member

Откуда:
Сообщений: 12953
chameleon82
- Получить вложения! (все вложения представлены как CLOB)
может быть сейчас с этим получше, во времена outlook express проблем хватало, особенно с переадресованными между разными почтовыми клиентами писем. проблемой было даже понять, что из миме-партийцев является телом самого сообщения.

Java Mail API вполне стабильное решение.
17 сен 12, 13:49    [13175683]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
SvDev
Member

Откуда: Челябинск
Сообщений: 1931
Для сравнения

Отправка вложений:

CES package http://www.oracletips.info/email_files.htm,
примеры http://www.uaex.edu/bknox/using_ces.email_files.htm

Прием вложений:

http://plsqlmailclient.sourceforge.net

(первое на utl_smtp, последнее через JavaMail)
17 сен 12, 14:08    [13175800]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
chameleon82, спасибо. почитала, но не уловила.
Может Ваш пакет отправлять таблицы в теле письма?
6 ноя 12, 18:30    [13428758]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
Какие именно таблицы? Не совсем понятно, о чем идет речь. Если о таблицах БД - то, разумеется, пакет для этого и создавался. Формат данных Вы должны подготовить сами. В принципе, пакет может отправлять все что угодно, Вам необходимо только подготовить необходимые данные в файл или в клоб и вложить в апи. Я лично без проблем отправляю через пакет генерируемые в pl/sql xml-excel файлы (несколько штук по 10-15 мегабайт каждое в одном письме) плюс из файловой системы подтягиваю логотип для подписи в письме. Если Вам необходимо архивировать, то сначала сохраните данные в файл, затем заархивируйте (решения можно поискать на форуме) и потом приложите в пакет.
6 ноя 12, 22:07    [13429492]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
-2-
может быть сейчас с этим получше, во времена outlook express проблем хватало, особенно с переадресованными между разными почтовыми клиентами писем. проблемой было даже понять, что из миме-партийцев является телом самого сообщения.


Главная цель, для которой был написан прием почты - возможность скармливать ораклу массивы данных. В принципе, найти в партициях то, что нужно зная что искать - не самая сложная задача )
На моем примере это массовая обработка транзакций ) почтовый сервер хорошо логгирует историю действий ленивых бухгалтеров ) Допустим, мы выгрузили массив данных в 1000 транзакций (в екселе бухам намного проще почему-то делать это), затем бухгалтер отправляет файл на почту ораклу, задав специальный заголовок, оракл получил письмо, обработал, выслал на обратный адрес результат загрузки с указанием ошибок. Ну вот сложно бухам через форму прикладывать файл или грузить через фтп )
6 ноя 12, 22:41    [13429617]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
chameleon82,

имелось в виду небольшие таблицы-отчеты в теле письма (используя html и css). Я эту проблему тут озвучила и меня направили сюда.
7 ноя 12, 11:57    [13431728]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
seregaLOKI
Member

Откуда:
Сообщений: 4
Я при помощи данного пакета реализовал отправку таблиц в виде html размером по несколько метров
8 ноя 12, 18:51    [13441863]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
seregaLOKI
Member

Откуда:
Сообщений: 4
Хотел поинтересоваться есть ли следующая возможность:

Выбираем нужные данные и их отправляем формате xls в качестве аттача с присваиванием ему имени, как я понял у вас реализовано присоединение файлов которые где то у нас хранятся заранее?
12 ноя 12, 08:44    [13456662]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
seregaLOKI
Хотел поинтересоваться есть ли следующая возможность:

Выбираем нужные данные и их отправляем формате xls в качестве аттача с присваиванием ему имени, как я понял у вас реализовано присоединение файлов которые где то у нас хранятся заранее?


Да.

 -- Из файла 
 PROCEDURE ADD_ATTACHMENT ( dirname IN varchar2
                          , filename IN varchar2
						  , mimetype IN varchar2 DEFAULT 'text/plain'
                          , name IN varchar2 DEFAULT NULL
                           );

 -- Из базы данных
 PROCEDURE ADD_ATTACHMENT ( blobloc IN blob
                          , filename IN varchar2
						  , mimetype IN varchar2 DEFAULT 'text/html'
                           );


Заметил, что некоторых интересует возможность добавления аттача в виде clob. Ну тут два пути, первый - дописать пакет с отправкой clob подобно отправке blob, и второй - просто конвертнуть клоб в блоб.
12 ноя 12, 15:14    [13459281]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
Пробую освоить пакет за который автору выражаю огромную благодарность - спасибо!!!. С обычными письмами все работает. Но не могу пока отправить результат запроса (таблица) в аттачменте. Мой код таков:

DECLARE
      blobloc BLOB;
    BEGIN
     MY_SCHEMA.MAIL_PKG.SET_MAILSERVER ('localhost',25);
     
     
     select TABLE_NAME, OWNER, INITIAL_EXTENT INTO blobloc from all_tables where rownum < 21;                        
     MY_SCHEMA.MAIL_PKG.ADD_ATTACHMENT(  blobloc 
                             ,'ReportResult.htm'
                             ,'text/html'
                            );                            

     MY_SCHEMA.MAIL_PKG.SEND( mailto => 'maya@company.ru'
                  , subject => 'Test subject'
                  , message => 'Some <b>bold</b> message!'
                  , mailfrom => 'REPORT SYSTEM <rep@prep>'
                  , mimetype => 'text/html'
                  , priority => 1
                  );
    END;


Как результат пишет:

ORA-06550: Строка 10, столбец 60:
PL/SQL: ORA-00947: не хватает значений для данных
ORA-06550: Строка 10, столбец 6:
PL/SQL: SQL Statement ignored

Спасибо за помощь.
19 ноя 12, 14:53    [13494980]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
Ura!
Member

Откуда:
Сообщений: 273
May12,

select TABLE_NAME, OWNER, INITIAL_EXTENT INTO blobloc from all_tables where rownum < 21;        

выбираете три поля, а засовываете в одно. да и то как то странно blobloc - это блоб, а вы пытаетесь туда засунуть совсем не блоб
19 ноя 12, 15:17    [13495201]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
Ura!,

пробовала конкатенировать:
select to_blob(TABLE_NAME||OWNER||INITIAL_EXTENT) INTO vBlob from all_tables where rownum < 21;

Результат:
ORA-01465: неверно задано шестнадцатеричное число

попробовала utl_raw.cast_to_raw, ну и конечно получила по почте прикрепленный ReportResult.htm с набором не понятных символов =(.
19 ноя 12, 15:41    [13495371]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
Ura!
Member

Откуда:
Сообщений: 273
May12,

Я так понял вам для проверки пихнуть блоб надо? Ну создайте свою табличку с полем BLOB запихните туда что нужно средствами тоада (ну или чем вы там пользуетесь) и считайте это поле в вашу переменную.
19 ноя 12, 15:52    [13495445]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
Ura!,
Мне надо отправить письмо с аттачментом в котором будет читаемая таблица. Лягушоноком пользуюсь.

Попробую, таблицу. Единственное я не пойму как из блоба родиться таблица в аттаче. Сообщу по результатам.
19 ноя 12, 16:22    [13495632]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
Ura!
Member

Откуда:
Сообщений: 273
May12,

:)
Из блоба сама таблица естественно не появится, так же как нельзя таблицу запихать в блоб так как вы пытались. Блоб это тип данных который может содержать чего угодно: исполняемые файлы, картинки, екселевские таблицы, html-ные таблицы и т.д. Оракл не разбирает чего у него там хранится, хранит как есть побайтно. Соответственно что вы туда положите, то он и отправит с письмом (сам пакетом не пользовался, но народ говорит, что оно так и есть)
19 ноя 12, 16:56    [13495869]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
Ura!,
тогда мне остается вариант положить результат селекта в директорию (используя UTL_FILE) и потом его послать с помощью пакета, разработанного автором топика. А если мне в одном письме нужно послать три файла?
Может автор пакета что-то подскажет или если кто решал аналогичную задачу. Спасибо.
19 ноя 12, 17:04    [13495918]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
chameleon82, помоги. =)
19 ноя 12, 19:45    [13496669]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
May12
Может автор пакета что-то подскажет или если кто решал аналогичную задачу. Спасибо.


В рамках Вашей темы.
20 ноя 12, 14:23    [13500459]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
88888888
Member

Откуда:
Сообщений: 2
Добрый день, может кто подсказать. Нужно отправить HTML-документ как прикрепление, а он постоянно приходит в теле письма в исковерканном виде.
15 янв 13, 09:49    [13770442]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
ОБНОВИЛ И ВЫЛОЖИЛ ПАКЕТ НА GIT

88888888
Добрый день, может кто подсказать. Нужно отправить HTML-документ как прикрепление, а он постоянно приходит в теле письма в исковерканном виде.


Возьмите версию с GitHub и попробуйте:

    DECLARE
      vClob CLOB;
    BEGIN

     -- Add attachment from CLOB
     vClob := '<HTML><TITLE>Clob Attachment Example</TITLE><BODY><b>This</b> is HTML clob attachment example</BODY></HTML>';
     MAIL_PKG.ADD_ATTACHMENT( vClob
                             ,'ClobResult.htm'
                             ,'text/html'
                            );

     MAIL_PKG.SEND( mailto => 'A. Ivanov <a.ivanov@yourcomany.ru>'
                  , subject => 'Test subject'
                  , message => 'Some <b>bold</b> message! See Attacments!'
                  , mailfrom => 'Oracle Notify <no-reply@yourcompany.ru>'
                  , mimetype => 'text/html'
                  , priority => 1
                  );
    END;
22 янв 13, 10:43    [13807398]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
LimonFX
Member

Откуда:
Сообщений: 77
chameleon82,

на ящики mail.ru и gmail почему-то не отсылает
Тестировал на примере 4) Extension Email with attacments
26 фев 13, 17:58    [13984558]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
LimonFX
Member

Откуда:
Сообщений: 77
Извиняюсь. Работает всё, просто комп без выхода в интернет был))
Но нашел другую странность, аутлук 2007 и выше почему-то письма с вложением принимает без вложения
26 фев 13, 18:33    [13984734]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
Полный пример можете привести?

Проверял на theBat и Outlook, все работало норм, сейчас аутлука под рукой нет.
27 фев 13, 13:28    [13988112]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
LimonFX
Member

Откуда:
Сообщений: 77
В качестве примера использовал 4) Extension Email with attacments
Причем если переслать это же письмо "без вложения" на другой адрес где используется тандерберд, то там вложение присутствует.
Не знаю, может быть тут от настроек аутлука многое зависит
27 фев 13, 15:11    [13989091]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
Vadim Romanenko
Member

Откуда: Харьков, Украина
Сообщений: 1388
Тоже пользовал пакет. Есть пара вроде бы багов :) Версию взял с GitHub
Отправляю текстовый файл из блоба.
Во-первых, веб-интерфейс Яндекса не видит аттачей. Веб-интерфейс ГМейла - видит, Бат - видит.
Во-вторых, какая-то чехарда с ситуацией, когда тело письма пустое. В этом случае в процедуре не добавляется имя первого файла почему-то :)
Вот этот стремный кусок:
      FOR x IN 1 .. attachments.count LOOP
          utl_smtp.write_data(v_Mail_Conn, '--'|| boundary || crlf );
          -- HOTFIX
          IF message IS NOT NULL OR x!=1 THEN
            utl_smtp.write_data(v_Mail_Conn, 'Content-Type: '||attachments(x).mimetype||';'|| crlf );
            utl_smtp.write_data(v_Mail_Conn, ' name="');
            utl_smtp.write_raw_data(v_Mail_Conn,utl_raw.cast_to_raw(attachments(x).name));
            utl_smtp.write_data(v_Mail_Conn, '"' || crlf);
            utl_smtp.write_data(v_Mail_Conn, 'Content-Transfer-Encoding: base64'|| crlf );
            utl_smtp.write_data(v_Mail_Conn, 'Content-Disposition: attachment;'|| crlf );
            utl_smtp.write_data(v_Mail_Conn, ' filename="' || ENCODE(attachments(x).name) || '"' || crlf);
          ELSE
           utl_smtp.write_data(v_Mail_Conn, 'Content-Type: '||attachments(x).mimetype||'; charset="utf-8"'|| crlf );
           utl_smtp.write_data(v_Mail_Conn, 'Content-Transfer-Encoding: base64'|| crlf );
          END IF;


Почему ТАК?
25 апр 13, 13:24    [14229701]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
Vadim Romanenko
Member

Откуда: Харьков, Украина
Сообщений: 1388
У себя в версии просто убрал прикол с разной отправкой первого файла и всех остальных. Вроде работает :)
Но на Яндексе все равно не показывает аттача... Может как-нибудь покручу в руках аттачи Яндекса...
25 апр 13, 13:49    [14229869]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
Vadim Romanenko

Почему ТАК?


предполагалось, что тело письма будет браться из аттача, если текст не задан. Вполне можно выпилить, т.к. в версии на гите письма с длинным текстом можно добавлять клобом.

а вот с яндексом беда. надо будет покрутить )
8 май 13, 06:41    [14271081]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
maxdart
Member

Откуда: spb
Сообщений: 31
Здравствуйте!

В первую очередь, хочу сказать большое спасибо автору за труды. Очень ценный пакет.

Есть пара вопросов по его работе. А именно...

1. При попытке получения почты с ящика не сервере mail.ru почта получается удачно, однако, не смотря на то, что в реальности письма имеют вложения, пакет их не видит. В чем может быть проблема? Встречалась ли она еще у кого-то, или я то-то делаю не так?
2. Не выходит получить почту с ящика на gmail. Там используется SSL, и порт не 110, а 995. Выходит, пакет не имеет поддержки gmail (по крайней мере, для получения почты).

Спасибо за ответы.
4 июн 13, 15:15    [14389452]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
maxdart
Здравствуйте!

В первую очередь, хочу сказать большое спасибо автору за труды. Очень ценный пакет.

Есть пара вопросов по его работе. А именно...

1. При попытке получения почты с ящика не сервере mail.ru почта получается удачно, однако, не смотря на то, что в реальности письма имеют вложения, пакет их не видит. В чем может быть проблема? Встречалась ли она еще у кого-то, или я то-то делаю не так?
2. Не выходит получить почту с ящика на gmail. Там используется SSL, и порт не 110, а 995. Выходит, пакет не имеет поддержки gmail (по крайней мере, для получения почты).

Спасибо за ответы.


Спасибо. Получение почты в части получения вложений крайне сыро написано (хотя странно, что у вас не видит, у меня на всех тестах иногда показывал больше вложений чем на самом деле из-за недоработанного парсинга, да и проблемы с получением вложений больших обьемов). К сожалению, у самого пока нет времени на дальнейшие доработки, но всегда кто-нибудь может помочь его подправить на GIT ;)
по п.2 пакет надо доработать процедурой типа SET_POPSERVER(p_host, p_port default 110, p_protocol ???); .
а если просто поменять порт на 995 не проходит?
5 июн 13, 10:34    [14392820]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
krupt
Member

Откуда: Екатеринбург
Сообщений: 20
Добрый день.
Подскажите, как отправить письмо с картинкой в теле письма, а не как вложение?
Допустим, если в Lotus вставить html-файл с <img src>, то он возьмет файл с диска и запихнет в письмо, но не будет отображать во вложениях.
Спасибо.
11 июн 13, 10:17    [14418860]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
sinitsa
Member

Откуда:
Сообщений: 204
krupt,

в протоколе такой возможности не припоминаю ( гугли на smtp rfc iso ).
отображеним занимается конкретный клиент,
если есть желание, делай заголовки под него.
но другой клиент будет отображать по другому.
13 июн 13, 09:40    [14426385]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
-2-
Member

Откуда:
Сообщений: 12953
sinitsa
в протоколе такой возможности не припоминаю ( гугли на smtp rfc iso ).
да-да, картинки это вотчина протокола smtp.
13 июн 13, 09:57    [14426491]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
krupt
Добрый день.
Подскажите, как отправить письмо с картинкой в теле письма?


Полагаю, Вы имели ввиду что-то вроде:
 BEGIN
	 MAIL_PKG.ADD_ATTACHMENT( ... , 'name' => 'mypicture.jpg'
							);
	 MAIL_PKG.SEND( ....
				  , message => 'Some <b>bold</b> message!'
				  , mailfrom => 'no-reply@yourserver.ru'

				  , sendername => 'Alert system'
				  , recipientname => 'Dear user'
	              );
	END;
13 июн 13, 12:12    [14427436]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
krupt
Добрый день.
Подскажите, как отправить письмо с картинкой в теле письма, а не как вложение?


Полагаю, Вы имели ввиду нечто такое:

 BEGIN
	 MAIL_PKG.ADD_ATTACHMENT( ... , 'name' => 'mypicture.jpg'
							);
	 MAIL_PKG.SEND( ....
				  , message => '<html> <body> Моя картинка <img src="mypicture.jpg"></body></html>'
				  , mailfrom => 'no-reply@yourserver.ru'

	              );
	END;


хотя как вложение оно также будет присутствовать. чтобы этого избежать, можно конвертировать бинарник картинки в base64 и складывать сразу в текст письма, хотя не все клиенты смогут отобразить. По другим решениям надо покурить smtp

Извиняюсь за пред сообщение, ктрл+ентер случайно нажал, не дописав )
13 июн 13, 12:16    [14427480]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
А вообще чтобы правильно вложить изображение, необходимо дописать пакет на наличие идентификатора у вложения,
Content-ID: <part1.08000907.01030003@domain.ru>


вернуть его с помощью функции в переменную и положить в текст письма в виде:

 <img src="cid:part1.08000907.01030003@domain.ru">  


вот только как формируются метки у такого идентификатора надо покурить

контент-ид положить после:
utl_smtp.write_data(v_Mail_Conn, 'Content-Transfer-Encoding: base64'|| crlf );

ну а чтобы не отображалось как вложение, допилить чтобы
Content-Disposition: inline;
или вообще отстуствовало данное свойство
13 июн 13, 12:32    [14427591]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
krupt
Member

Откуда: Екатеринбург
Сообщений: 20
chameleon82,

Внес изменения в Ваш код.

Добавил поле inline в типе attach_row
type attach_row is record ( dirname varchar2(30)
                           , filename varchar2(30)
                           , name varchar2(30)
                           , mimetype varchar2(30)
                           , blobloc blob
                           , clobloc clob
                           , attachtype varchar2(30)
                           , inline BOOLEAN := FALSE
                           );

Добавил параметр pinline во все процедуры Add_attachment, например:
 PROCEDURE ADD_ATTACHMENT ( dirname IN varchar2
                          , filename IN varchar2
                          , mimetype IN varchar2 DEFAULT 'text/plain'
                          , name IN varchar2 DEFAULT NULL
                          , pinline BOOLEAN := FALSE
                           );


В процедуре Send сделал следующее
    IF MAIL_PKG.attachments.count>0 THEN
      FOR x IN 1 .. MAIL_PKG.attachments.count LOOP
          utl_smtp.write_data(v_Mail_Conn, '--'|| boundary || crlf );
          -- HOTFIX
          IF message IS NOT NULL OR x!=1 THEN
            utl_smtp.write_data(v_Mail_Conn, 'Content-Type: '||MAIL_PKG.attachments(x).mimetype||';'|| crlf );
            utl_smtp.write_data(v_Mail_Conn, ' name="');
            utl_smtp.write_raw_data(v_Mail_Conn,utl_raw.cast_to_raw(MAIL_PKG.attachments(x).name));
            utl_smtp.write_data(v_Mail_Conn, '"' || crlf);
            utl_smtp.write_data(v_Mail_Conn, 'Content-Transfer-Encoding: base64'|| crlf );
[b]
            IF Attachments(x).InLine THEN
              utl_smtp.write_data(v_Mail_Conn, 'Content-Disposition: inline;'|| crlf );
            ELSE
                  utl_smtp.write_data(v_Mail_Conn, 'Content-Disposition: attachment;'|| crlf );
            END IF;
[/b]
            utl_smtp.write_data(v_Mail_Conn, ' filename="' || MAIL_PKG.ENCODE(MAIL_PKG.attachments(x).name) || '"' || crlf);
          ELSE
           utl_smtp.write_data(v_Mail_Conn, 'Content-Type: '||MAIL_PKG.attachments(x).mimetype||'; charset="utf-8"'|| crlf );
           utl_smtp.write_data(v_Mail_Conn, 'Content-Transfer-Encoding: base64'|| crlf );
          END IF;
          utl_smtp.write_data(v_Mail_Conn, crlf );
          IF MAIL_PKG.attachments(x).attachtype = 'FILE' THEN
...


Вроде работает, вот только проблема. Все вложения идут в строке поочереди, как сделать чтобы они были в разных строках?
13 июн 13, 13:17    [14427862]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
krupt
Member

Откуда: Екатеринбург
Сообщений: 20
chameleon82,

Не видел, что вы уже написали про inline :)
13 июн 13, 13:20    [14427881]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
krupt
Member

Откуда: Екатеринбург
Сообщений: 20
chameleon82,

Отправку делаю так:
  mail_pkg.Add_Attachment( 'REPORTS', 'logo.jpg', 'image/jpeg', 'logo.jpg', TRUE);
  mail_pkg.Send( '1@mail.ru', 'Test attach', 'Some <b>bold</b> message!<br>', 'Sender', 'text/html');
13 июн 13, 13:36    [14427991]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
krupt
chameleon82,

Внес изменения в Ваш код.

Добавил поле inline в типе attach_row


Вроде работает, вот только проблема. Все вложения идут в строке поочереди, как сделать чтобы они были в разных строках?


Я нашел минутку, решил сам покурить ))

DECLARE
 vClob CLOB :=  UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.base64_decode(UTL_RAW.CAST_TO_RAW(
  'R0lGODlhbgAeAPQAAPFTfP7y9f3j6vBFce0oW/vV3/m4yfR/nfBTe+43Zvebs/Jih/Nwku0oWviq' 
||'vvrF0/epvf3w9PFhhvzi6e42ZfR+nPvU3vNvkfaasu9EcPm3yPWMp/aNqPrG1OwaUP///yH/C01T'
||'T0ZGSUNFOS4wGAAAAAxtc09QTVNPRkZJQ0U5LjAgJPn1cgAh/wtNU09GRklDRTkuMBgAAAAMY21Q'
||'UEpDbXAwNzEyAAAAA0gAc7wALAAAAABuAB4AAAX/4CeOY6Asiad6BKAIZCzPdG3feH4LzOr/i4Ju'
||'SCwac5yf8ncIHJ/Q6CwAWFpXA6d0y9UFBtewJ9stm2NVcZh8bm+TVgpirsrM7wjVwc1/CpQXDzIZ'
||'FTN5Hh19ikM9Kw2CMhYeEzITKwA2CgALBiQBHByJHwYcAKYAHDAiBaCqI6ypIgqgQiICoFofDgun'
||'B50fJgymCxwGAT8YIxEPzA95EMwYlB8VPrUycCqiHx0qHCJpTCJw2+PaIisJI92I4EqYX+8OPg0j'
||'Gg1XFCIR+Ct7M2AI6FnnzZ0HU2DOkYux8IMPUewSFVDR4pSDDwconkK1wAeCERLCJPuA4ceAKXrA'
||'/6gTwe7bhzQjFBRsOKKhD0zczsn0cBGNClciUqzIMMJCPyUNIoigoGTGPA8GMnpQ1dIgCRWYaJpr'
||'59AHjIgftIroyDOGkmkfIoRUUugDhCVARTQKYEBFz6ovVYyo6+GbWJsHVTDI2Q6Ogg6IOzjhe/Ca'
||'Egkx7v2YduhHuaAe1B3zMJiwyzSgDggsfI4E4FI/wWbz4VKqYCdLJCgtevSCiAdWLv/hLEIly4J5'
||'lfz7W9pbS9VLFKxLyGLikgYaSLxVYUHEBSvXRDxV8hV4GgBCO4ctXbN43w8pCPBNJDaGgtHgr8ge'
||'UUeEJSsyGilRjhfmbgJaEMdVQU+RxR55NBQwGvlZVtiGjgcNzMHUEifFIFACifG1gGdWYQQcHL+U'
||'N+B56D00Hlc2JLSTFRvQp4YH/7wiGAnpcRicCAEIREB3YxiQ2CfmubRaIuwM4CNiMNxSTFQqJLAb'
||'hBtIcAcEI0ynRnYf7KTcCI0U0J9eW3U22kOn4ThmIjm+Q9gPFzXiYCRHrYENC0DxZYAAAm3ZUYXA'
||'BLQKg5kVwFctAoW4UwJaFAAoAXsIwJwHnNiiQnQyQBBnGJctoukMGVFQwQbQYFDBhC9uuOmpNTz6'
||'4g+IouqqDPGs+gMBWL76aqyyBmrrrp64VmouvAbbQThXAJBpsMHeQqwKAxxQK7KbhgAAOw=='
)) )
;
 v_id varchar2(25);
BEGIN
     
     MAIL_PKG.ADD_ATTACHMENT( vClob
                             ,'image.gif'
                             ,'image/gif'
                             , disposition => MAIL_PKG.DISPOSITION_INLINE
                            );
     v_id := MAIL_PKG.LAST_ATTACHMENT_ID;

     MAIL_PKG.SEND( mailto => 'A Ivanov <a.ivanov@yourcompany.ru>'
                  , subject => 'Письмо с логотипом'
                  , message => 'Я летаю авиакомпанией  <img src="cid:'|| v_id || '">'                  
                  , mailfrom => 'Уведомление <no-reply@yourcompany.ru>'
                  , mimetype => 'text/html'
                  );
END;


Изменения выложил в GIT
13 июн 13, 14:26    [14428416]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
krupt
Member

Откуда: Екатеринбург
Сообщений: 20
chameleon82,

Подскажите на счет
krupt
Все вложения идут в строке поочереди, как сделать чтобы они были в разных строках?
13 июн 13, 14:43    [14428600]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
krupt
chameleon82,

Подскажите на счет
krupt
Все вложения идут в строке поочереди, как сделать чтобы они были в разных строках?


не совсем понял вопрос.
Для переноса строки в html используется тег <br>
14 июн 13, 05:21    [14431546]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
LimonFX
Извиняюсь. Работает всё, просто комп без выхода в интернет был))
Но нашел другую странность, аутлук 2007 и выше почему-то письма с вложением принимает без вложения


проверил на аутлук 2010, все работает корректно. с последней версией пакета также корректно отображаются и вложения и встроенные изображения.
14 июн 13, 07:32    [14431595]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
chameleon82, я почитала и поняла, что Ваш пакет может работать с прикрепленными к входящим письмам файлами. Это верное понимание или нужно вчитаться?
13 авг 13, 16:39    [14703493]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
May12,

да, все верно, пример получения вложений во входящей почте описан в комментариях в пакете
14 авг 13, 09:03    [14705841]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
Добавил примеры с пояснениями на GIT
14 авг 13, 10:55    [14706340]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
chameleon82, спасибо, но у меня как всегда не работает.
История стирания ногтей по локти:
восхищаясь тем, что на свете есть такие люди как Вы, я взяла Ваш пакет, откомпилировала и хотела послать письмо себе, процедура отработала, но письма не пришло. Меня насторожили вот эти строчки из Вашего примера:

  -- Устанавливаем почтовый сервер для отправки почты, отличный от localhost:25
     MAIL_PKG.SET_MAILSERVER ('localhost',25);
     -- Устанавливаем данные для авторизации на почтовом сервере
     MAIL_PKG.SET_AUTH ('a.nekrasov','password'); 


вместо localhost написала адрес exchange сервера. ну и дальше по сути и руководствуясь здравым смыслом.
Запустила, процедура, повторюсь, отработала успешно но ничего не пришло. Должна быть какая-то "дружба" (или любовь) между сервером Oracle и сервером электронной почты?

Причем пример от Кайта у меня отработал корректно (без вложения, правда). Но предвкушая какие фишечки несет в себе Ваш пакет я бы хотела, чтобы он у меня заработал. вот и пишу к Вам...
14 авг 13, 19:47    [14709771]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
May12,

Попробуйте не указывать авторизацию, в большинстве случаев она не требуется (Например, в примере Т.Кайта ее нет). Если она установлена в сессии, то сбросить ее можно так:
     MAIL_PKG.SET_AUTH (); 

Попробуйте отправить через локалхост, обычно на оракле уже крутится почтовый демон.
Возможно эксчендж проверяет соответствие отправителя, укажите в параметре mailfrom реальный почтовый ящик.
Если не помогло - попросите почтового администратора разобрать логи.
15 авг 13, 08:19    [14711030]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
chameleon82, сделала с
MAIL_PKG.SET_AUTH (); 

письмо пришло, потом закоментировала и все работает с локал хостом.
Спасибо и добра Вам.
15 авг 13, 11:09    [14711687]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
chameleon82, здравствуйте. Пытаюсь забрать почту (посчитать количество писем) с сервера, получаю такую ошибку:
Error at line 1
ORA-29260: ошибка сети: не соединен
ORA-06512: на "MAYA.MAIL_PKG", line 522
ORA-06512: на line 28
ORA-29260: ошибка сети: TNS:нет прослушивателя

Пробовала и с локал хостом и с явным указанием exchange сервера (+ пароль и логин). Это от того что нет "дружбы" между почтовым сервером ораклом (ну помимо кривизны рук)?

MAIL_PKG.DEBUG := TRUE; расскоментирован, но подробнее описание ошибки не вижу.
19 авг 13, 12:22    [14724877]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
May12
chameleon82, здравствуйте. Пытаюсь забрать почту (посчитать количество писем) с сервера, получаю такую ошибку:
Error at line 1
ORA-29260: ошибка сети: не соединен
ORA-06512: на "MAYA.MAIL_PKG", line 522
ORA-06512: на line 28
ORA-29260: ошибка сети: TNS:нет прослушивателя


Какая версия оракла? С 10-ой версии необходимо указывать разрешения по доступу в ACL-листах


May12
MAIL_PKG.DEBUG := TRUE; расскоментирован, но подробнее описание ошибки не вижу.

DBMS_OUTPUT включите и смотрите его, там весь процесс общения с сервером, но ввиду ошибки выше общение еще даже не начиналось
19 авг 13, 12:44    [14725047]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
chameleon82
Какая версия оракла?

10.2. указывать разрешение по доступу это как тут написано?


chameleon82
DBMS_OUTPUT включите

Ясно.
19 авг 13, 13:23    [14725322]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
May12,

не, там про 11 написано. сорри.
19 авг 13, 13:47    [14725486]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
Видимо, мне не забрать почту. =(
19 авг 13, 14:59    [14725950]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
-2-
Member

Откуда:
Сообщений: 12953
May12
Видимо, мне не забрать почту. =(
возможно данный пакет умеет забирать почту только через попу, а на эксчендже доступ к ней не проходит через порты.
19 авг 13, 15:10    [14726020]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
-2-,
автор
возможно данный пакет умеет забирать почту только через попу,


да, через pop3. А на эксчендже IMAP и надо админов просить что-то сделать чтобы почту забирать через pop3.
что же делать...
19 авг 13, 17:39    [14727065]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
May12
-2-,
автор
возможно данный пакет умеет забирать почту только через попу,


да, через pop3. А на эксчендже IMAP и надо админов просить что-то сделать чтобы почту забирать через pop3.
что же делать...


Да, до IMAP еще руки не дошли, только с POP3 пока работает
20 авг 13, 12:27    [14730033]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
May12
что же делать...

Настройте пересылку на ящик, к которому есть доступ по pop
20 авг 13, 12:30    [14730060]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
chameleon82, по телнету 110 порт открывается. выполняю код:
 set dbms_output on;
 
 declare
 
 BEGIN
       
       MAIL_PKG.DEBUG := TRUE;
 
       MAIL_PKG.SET_MAILSERVER ('тут и ip пробовала и доменное имя');
       MAIL_PKG.SET_AUTH ('maya@company.ua','pass');
 
       MAIL_PKG.MAIL_CONNECT;
      
       DBMS_OUTPUT.PUT_LINE('Total mails count:'||mail_pkg.mailbox.count);
       
       MAIL_PKG.MAIL_DISCONNECT;

    EXCEPTION WHEN OTHERS THEN
      
      MAIL_PKG.MAIL_DISCONNECT;
    END;


процедура отрабатывает, но количества писем не возвращает, в dbms_output лога общения с сервером не выводит. уже близко. помогите, молю.
20 авг 13, 18:46    [14732518]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
May12
процедура отрабатывает, но количества писем не возвращает, в dbms_output лога общения с сервером не выводит. уже близко. помогите, молю.

Забыл уточнить:
  MAIL_PKG.DEBUG_LEVEL := MAIL_PKG.DEBUG_ALL;

Скорее всего проблема тут:
   MAIL_PKG.SET_AUTH ('maya@company.ua','pass');

надо:
  MAIL_PKG.SET_AUTH ('maya','pass');
21 авг 13, 06:02    [14733695]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
chameleon82, уже совсем близко =)), но пока результат таков:

+OK The Microsoft Exchange POP3 service is ready.
DEBUG:-ERR Command is not valid in this state.
DEBUG:+OK Microsoft Exchange Server 2010 POP3 server signing off.
21 авг 13, 10:18    [14734362]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
может проблема в ssl?
For exchange 2010, by default, the server would need the client use ssl for pop3.
21 авг 13, 10:21    [14734397]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
May12
может проблема в ssl?
For exchange 2010, by default, the server would need the client use ssl for pop3.


Возможно. Обновил немного пакет, попробуйте еще раз с новой версией вывести лог
21 авг 13, 12:23    [14735275]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
chameleon82, заработало. Ошибка в моем случае была в домене и доступности порта.

Для будущих пользователей пакета перед получением почты по протоколу pop3:
Проверьте из cmd по телнету доступность 110 порта почтового сервера:
telnet exchange_server_addr 110
Если порт закрыт, то побеспокойте администратора почтового сервера, чтобы он открыл порт. Также важно чтобы SSL шифрование по этому порту отсутствовало (в интернете пишут, что оно иногда может стоять по умолчанию).

chameleon82, спасибо и добра Вам.
21 авг 13, 12:36    [14735432]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
Basil A. Sidorov
Member

Откуда:
Сообщений: 7273
May12
Также важно чтобы SSL шифрование по этому порту отсутствовало
SSL-шифрования на 110 порту не может быть по определению. Или STARTTLS или 995-й порт.
21 авг 13, 15:17    [14736749]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
Basil A. Sidorov,
да, не может. не поспоришь.
21 авг 13, 17:45    [14738058]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
Ребят, не подскажите с чем связано странное поведение пакета =)) или не пакета.

Если отправлять письмо с вложением, то оно не отправляется, не приходит на почту. Если закомментировать функцию MAIL_PKG.ADD_ATTACHMENT и снова выполнить, то приходит письмо с аттачментами!!! В письме столько аттачментов сколько раз была выполнена ранее процедура с незакомментированной MAIL_PKG.ADD_ATTACHMENT. Т.е. складывается впечатление, что в письмо набиваются файлы и потом отправляются.
7 окт 13, 11:01    [14932560]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
А воооот и ошибка:
ORA-06502: PL/SQL: : буфер символьных строк слишком маленький ошибка числа или значения
ORA-06512: на "MAYA.MAIL_PKG", line 163
ORA-06512: на line 9
7 окт 13, 11:04    [14932590]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
но как её пофиксить не пойму =(( вот на этой строке пакета:
LAST_ATTACHMENT_ID := GENERATE_CONTENT_ID(MAIL_PKG.attachments.count);


chameleon82, need your help!
7 окт 13, 11:30    [14932768]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
maddistortion
Member

Откуда: Novosibirsk
Сообщений: 123
May12,

если я правильно понял функция
 FUNCTION GENERATE_CONTENT_ID(n number) RETURN VARCHAR2 IS
 BEGIN
   RETURN 'mailpkg'||n||'_'||TO_CHAR(sysdate,'YYMMDD')||'.'||TO_CHAR(dbms_utility.get_time);
 END;

возвращает значение большей длины чем
LAST_ATTACHMENT_ID VARCHAR2(25) := NULL;
7 окт 13, 13:41    [14933610]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
maddistortion, спасибо за отклик.
Увеличила до 500
 LAST_ATTACHMENT_ID VARCHAR2(500) := NULL;

ошибка:
ORA-06502: PL/SQL: : буфер символьных строк слишком маленький ошибка числа или значения
ORA-06512: на "MAYA.MAIL_PKG", line 164
ORA-06512: на line 11
7 окт 13, 15:26    [14934480]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
maddistortion
Member

Откуда: Novosibirsk
Сообщений: 123
May12,
 type attach_row is record ( dirname varchar2(30)
                           , filename  varchar2(30)
                           , name  varchar2(30)
                           , mimetype varchar2(30)
                           , blobloc blob
                           , clobloc clob
                           , attachtype varchar2(30)
                           , contentid varchar2(25)
                           , disposition varchar2(25) default 'attachment'
                           );


contentid тоже попробуйте увеличить
7 окт 13, 15:42    [14934584]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
maddistortion,

Вы - чудо. Добра Вам.
7 окт 13, 15:56    [14934696]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
Я извиняюсь, вопрос уже поднимался, в том числе мной, но в других ветках и безрезультатно.
Сейчас хочу отправить таблицу в теле письма с помощью замечательного пакета mail_pkg. Наставьте на путь истинный? Что делать?

Мои потуги вот:

DECLARE
   
   tables_in_clob clob;
   cursor cur_tab_1
   is 
   select '<TD>'||'Помоги'||'</TD>' ||
          '<TD>'||'тупой'||'</TD>'||
          '<TD>'||'учиться!!!'||' </TD>'||
           chr(10)  as STR
      FROM DUAL CONNECT BY LEVEL < 5;
      
   
    STRING_TO_BODY VARCHAR2(1000); 
    
    v_id varchar2(50); 

BEGIN
   
DBMS_LOB.createtemporary (tables_in_clob, TRUE); 
DBMS_LOB.OPEN (tables_in_clob, DBMS_LOB.lob_readwrite); 


DBMS_OUTPUT.PUT_LINE('Формируем CLOB для вставки в почтовое сообщение.');
  
open cur_tab_1; --- курсор с таблицей
 
        LOOP 
            
            Fetch cur_tab_1 INTO STRING_TO_BODY;
            
            EXIT WHEN cur_tab_1%NOTFOUND;
            
            DBMS_LOB.writeappend (tables_in_clob, length(STRING_TO_BODY), STRING_TO_BODY);
             
            DBMS_OUTPUT.PUT_LINE(DBMS_LOB.GETLENGTH(tables_in_clob));
            
        END LOOP; 

DBMS_OUTPUT.PUT_LINE('CLOB для отправки сформирован.');


DBMS_OUTPUT.PUT_LINE('Отправляем CLOB.');

                           MAIL_PKG.ADD_ATTACHMENT(tables_in_clob -- дата
                             ,'logo.gif' -- имя файла в письме
                             ,'text/html' -- mime тип
                             , disposition => MAIL_PKG.DISPOSITION_INLINE
                            );
    
    v_id := MAIL_PKG.LAST_ATTACHMENT_ID;
    
    MAIL_PKG.SEND( mailto =>   'maya_vetrova@почта.ru'
                  , subject => 'Письмо с таблицей'
                  , message => 'Вот Вам таблица  <img src="cid:'|| v_id || '">'                  
                  , mailfrom =>'Уведомление <no-reply@yourcompany.ru>'
                  , mimetype =>'text/html'
                  );

DBMS_OUTPUT.PUT_LINE('Отправка CLOB в качестве тела письма завершена.');

close cur_tab_1;

DBMS_LOB.CLOSE (tables_in_clob); 
DBMS_LOB.freetemporary (tables_in_clob);


EXCEPTION
   WHEN NO_DATA_FOUND THEN
      NULL;
   WHEN OTHERS THEN
      NULL;
END;
16 окт 13, 10:59    [14978511]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
andreiz
Member

Откуда:
Сообщений: 28
chameleon82,
интересно, у меня другая задача - читать письма с exchange 7, сохранять тело как "чистый" текст в CLOB, ну и как BLOB, сохрранять все аттачки как BLOB. делаю на яве в банке, больше всего трудностей с коонвертированием тела в "чистый" текст. у кого есть опыт поделитесь.
заранее спасибо.
всего.
16 окт 13, 11:23    [14978673]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
andreymx
Member

Откуда: Запорожье
Сообщений: 41790
May12
EXCEPTION
   WHEN NO_DATA_FOUND THEN
      NULL;
   WHEN OTHERS THEN
      NULL;
END;
интересно, как ты поймёшь, где и когда произошла ошибка?
16 окт 13, 11:37    [14978796]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
andreiz, если я правильно поняла смотрите тут https://forums.oracle.com/thread/2398323
там создаются две таблички, java-класс в базе и обертка , в результате из ящика данные загружаются в две таблицы - боди и атачменты.
16 окт 13, 11:58    [14978968]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
andreymx, упс, забыла удалить. но мне кажется я концептуально что-то не то делаю. в принципе не пойму как таблицу засунуть в тело письма.
16 окт 13, 12:01    [14978993]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
andreiz
Member

Откуда:
Сообщений: 28
May12,
да всё примерно так, одна беда
"// -- Body is also multipart (both plain text and html)."
начиная с "exchange server 2007" он не шлёт больше "multipart и даже plain text" только html плюс всякие там encoding...
а так очень похоже
спасибо
16 окт 13, 12:57    [14979477]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
chameleon82, без Вас не справлюсь. Помогите отправить таблицу
 select '<TD>'||'Помоги'||'</TD>' ||
          '<TD>'||'тупой'||'</TD>'||
          '<TD>'||'учиться!!!'||' </TD>'||
           chr(10)  as STR
      FROM DUAL CONNECT BY LEVEL < 5;


в теле письма? Молю...
16 окт 13, 13:07    [14979567]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
andreiz
Member

Откуда:
Сообщений: 28
May12,

попробуй заменить '<' на '<' и '>'на '>'


select '<TD>'||'Помогу'||'</TD>' ||
... FROM DUAL CONNECT BY LEVEL < 5;
16 окт 13, 14:09    [14980024]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
andreiz
Member

Откуда:
Сообщений: 28
сайт не пропустил, пробую ещё раз
'<' на '&'||'lt;' и '>'на '&'||'gt;'

select '&'||'lt;'||'Помогу'||'&'||'gt;'||
... FROM DUAL CONNECT BY LEVEL < 5;
16 окт 13, 14:17    [14980088]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
andreiz, =((
16 окт 13, 15:42    [14980881]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
K790
Member

Откуда:
Сообщений: 550
May12,

mb
FOR I IN (select owner, object_name  from all_objects)
  LOOP
     v_message:=v_message||'<tr><td>'||i.owner||'</td><td>'||i.object_name ||'</td></tr>'||utl_tcp.CRLF;
  END LOOP;
16 окт 13, 16:16    [14981204]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
K790
Member

Откуда:
Сообщений: 550
May12,

sry

v_message:=v_message||'<table style="border: solid 0px #cccccc"  cellspacing="0" cellpadding="0"><tr BGCOLOR=#000099>';
FOR I IN (select owner, object_name  from all_objects)
  LOOP
     v_message:=v_message||'<tr><td>'||i.owner||'</td><td>'||i.object_name ||'</td></tr>'||utl_tcp.CRLF;
  END LOOP;
v_message:=v_message||'</table></body></html>'||utl_tcp.CRLF;
16 окт 13, 16:21    [14981263]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
K790, спасибо. Так и делаю. Читаю отсюда. вот только кинуть на почту это хочется все-таки с использование mail_pkg.
16 окт 13, 16:48    [14981555]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
May12, кидай в свое удовольствие через:

 MAIL_PKG.SEND( mailto => 'A. Ivanov <a.ivanov@yourcomany.ru>, O.Petrov <o.petrov@yourcompany.ru>'
                  , subject => 'Test subject'
                  , message => v_your_table_with_CSS_and_HTML
                  , mailfrom => 'Oracle Notify <no-reply@yourcompany.ru>'
                  , mimetype => 'text/html'
                  , priority => 1
                  );


=))
17 окт 13, 16:45    [14986721]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
May12
chameleon82, без Вас не справлюсь. Помогите отправить таблицу
 select '<TD>'||'Помоги'||'</TD>' ||
          '<TD>'||'тупой'||'</TD>'||
          '<TD>'||'учиться!!!'||' </TD>'||
           chr(10)  as STR
      FROM DUAL CONNECT BY LEVEL < 5;


в теле письма? Молю...


Вот никак не могу понять, в чем проблема :)

DECLARE
 message CLOB;
BEGIN
 message := '
<HTML>
       <HEAD>
              <STYLE>
                     table td {color: red; font: 25px solid red;padding:15px}
              </STYLE>
       </HEAD>
       <BODY>
             <TABLE BORDER=1>
                 <TR><TH>Что</TH><TH>Кому</TH><TH>Что делать</TH></TR>';

FOR x IN (
select '<TR><TD>'||'Помоги'||'</TD>' ||
          '<TD>'||'тупой'||'</TD>'||
          '<TD>'||'учиться!!!'||' </TD></TR>'||
           chr(10)  as STR
      FROM DUAL CONNECT BY LEVEL < 5)
LOOP
 message := message || x.STR;
END LOOP;
 message := message || '
         </TABLE>
    </BODY>
</HTML>
';
 
   MAIL_PKG.SEND( mailto =>   'maya_vetrova@почта.ru'
                  , subject => 'Письмо с таблицей'
                  , message => message                  
                  , mailfrom =>'Уведомление <no-reply@yourcompany.ru>'
                  , mimetype =>'text/html'
                  );
 
END;          
18 окт 13, 09:26    [14995565]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
Кстати, Ваш запрос в PLSQL в Oracle9i выдаст одну строку вместо 4-ех, в версиях старше будет все норм. Это известная бага 9-го оракла при выборе произвольных данных из таблички DUAL. Будьте внимательны
18 окт 13, 09:34    [14995630]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
Вячеслав Любомудров
Member

Откуда: Владивосток
Сообщений: 17275
Это бага не оракла, а инструмента
18 окт 13, 09:43    [14995690]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
andreiz
chameleon82,
интересно, у меня другая задача - читать письма с exchange 7, сохранять тело как "чистый" текст в CLOB, ну и как BLOB, сохрранять все аттачки как BLOB. делаю на яве в банке, больше всего трудностей с коонвертированием тела в "чистый" текст. у кого есть опыт поделитесь.
заранее спасибо.
всего.


Пока пакет может только с некоторыми ограничениями забирать почту с pop3, сейчас как раз работаю над получением почты через протоколы IMAP и MAPI (с последним работает exchange).
С конвертированием тела в текст в данном пакете особых проблем не наблюдалось, по крайней мере, с английским текстом проблем точно нет. Русский текст в моих тестах вполне декодируется, но я тестировал не на всех кодировках. Для приема почты с помощью mail_pkg попробуйте пересылать почту на pop3 ящик.
18 окт 13, 09:44    [14995704]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
mr Red
Member

Откуда:
Сообщений: 143
пакет вылетает при попытке отправить аттач из blob

ORA-06502: PL/SQL: : character string buffer too small ошибка числа или значения
ORA-06512: на "STAGE.MAIL_PKG", line 179
ORA-06512: на line 29

прочитал ветку, проставил все varchar(25) в varchar(500), не помогло
все равно вылетает там же.

что делать?
24 окт 13, 10:14    [15024387]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
mr Red
Member

Откуда:
Сообщений: 143
mr Red
пакет вылетает при попытке отправить аттач из blob

ORA-06502: PL/SQL: : character string buffer too small ошибка числа или значения
ORA-06512: на "STAGE.MAIL_PKG", line 179
ORA-06512: на line 29

прочитал ветку, проставил все varchar(25) в varchar(500), не помогло
все равно вылетает там же.

что делать?


все, вопрос снят
заменил практически все varchar(n) на varchar(500)
помогло
24 окт 13, 10:21    [15024422]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
oleggy
Member

Откуда:
Сообщений: 2
Всем привет.
Вопрос скорее всего к chameleon82 или может быть кто то другой знает.
Данный скрипт отправки почты возможно выполнить в SQL Plus ?
11 ноя 13, 11:20    [15107409]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
oleggy, это мой пятый совет в форуме (пытаюсь немного помочь -2-): вам нужно скомпилировать предложенный пакет и выполнять из него процедуры. инструмент (sql plus или что-то другое) не имеет значения. Однако с таким объемом кода, на мой взгляд, удобнее работать в Toad или pl/sql developer.
12 ноя 13, 10:29    [15113447]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
Друзья, подскажите пожалуйста как отправить почту на внешний домен? приходит вот такая "отбивка":

Не удалось выполнить доставку следующим получателям или группам:
maya_vetrova@othercompanydomain.com
Неверный формат адреса электронной почты. Допустимые адреса выглядят следующим образом: username@contoso.com. Проверьте адрес электронной почты получателя и повторите попытку отправки сообщения.

Диагностические сведения для администраторов:

Формирующий сервер: localhost.localdomain

maya_vetrova@othercompanydomain.com
#< #5.1.3 SMTP; 553 The sender must not be from a protected domain as the sender's IP is in the Inbound Mail Relay list.> #SMTP#

т.е. понятно что отправка, видимо, запрещена. Каким способом сделать отправку возможной?
12 ноя 13, 11:25    [15113756]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
May12
Друзья, подскажите пожалуйста как отправить почту на внешний домен? приходит вот такая "отбивка":

т.е. понятно что отправка, видимо, запрещена. Каким способом сделать отправку возможной?


Ну это Вам к администратору почтового сервера, сложно сказать, какие фильтры у него настроены. Попробуйте в адресе почты отправителя указать правильный почтовый домен (или существующую учетную запись).
12 ноя 13, 13:54    [15114994]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
chameleon82
Попробуйте в адресе почты отправителя указать правильный почтовый домен (или существующую учетную запись).

да, так и сделала и получила "отбивку". =)
12 ноя 13, 14:56    [15115637]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
PooH_2
Member

Откуда:
Сообщений: 268
Ну вам же пишут "Допустимые адреса выглядят следующим образом: username@contoso.com"
Это настройка вашего почтового сервера, он другую почту слать не хочет. Надо это ограничение изменить или отключить. Но к ораклу это уже не имеет никакого отношения.
12 ноя 13, 16:00    [15116204]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
l_kator
Member

Откуда: München
Сообщений: 535
chameleon82,
спасибо вам огромное!! Вы спасли мой мозг :)

У меня всего 2 вопроса:
Как подписаться на рассылку обновленной версии пакета?
Куда слать пиво(цветы/вино/шоколад/котлеты)?
4 дек 13, 16:56    [15240857]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
chameleon82, с наступающим и добра Вам.

Повторно наткнулась на проблему ограничения длины, в в этот раз, названия файла. Чтоб люди еще меньше мучились предлагаю заменить type attach_row на:
type attach_row is record ( dirname varchar2(30)
                           , filename  varchar2(256)
                           , name  varchar2(256)
                           , mimetype varchar2(30)
                           , blobloc blob
                           , clobloc clob
                           , attachtype varchar2(30)
                           , contentid varchar2(256)
                           , disposition varchar2(25) default 'attachment'
                           );
24 дек 13, 11:31    [15338184]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
-2-
Member

Откуда:
Сообщений: 12953
May12,

перекомпилируй с nls_length_semantic=char. и имей ввиду, что большинство файловых систем не поддерживают имена более 255 символов.
24 дек 13, 12:07    [15338499]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
l_kator
chameleon82,
спасибо вам огромное!! Вы спасли мой мозг :)

У меня всего 2 вопроса:
Как подписаться на рассылку обновленной версии пакета?
Куда слать пиво(цветы/вино/шоколад/котлеты)?


Пожалуйста ) Свежая версия пакета всегда на гитхабе

May12
chameleon82, с наступающим и добра Вам.

И Вас с наступающим ) Ваше замечание пофиксил ;)

И всем тоже счастливого Нового года! )
31 дек 13, 10:32    [15368106]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
Vadim Romanenko
Member

Откуда: Харьков, Украина
Сообщений: 1388
Привет всем!

Для того, чтоб не испытывать проблем, как у May12, я бы категорически предложил всем переменным типа varchar2 выдать размер с запасом. Например, в текущем варианте под папку отдается 30 символов. Люди, ну чем Вы думаете?? Под имя файла 256, под имя папки - 30 :) Да кто в Оракле трясется сегодня над каждым байтом??? Тем более в пакете, тем более, когда это имя и папка не хранится в БД? Сегодня ОЗУ считается гигабайтами, а не килобайтами!

Я бы рекомендовал под папку выделить 512 символов, под имя - ИМХО хватило бы 128, но пусть таки будет 256. Минимальным размером варчара советовал бы установить 64 символа, а не эти игры с 20-25-30. Потому что в связи с такой прижимистостью ПОСТОЯННО возникают различные артефакты. Вот например - недавно на Гитхабе оставлял отзыв, что из-за прижимистости были баги с отправкой писем начиная с октября (длина номера месяца переходила в двузначную величину). Ну и кому это надо??? Вылавливать такие баги...

С уважением, Вадим.
22 янв 14, 13:20    [15451890]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
Vadim Romanenko
Member

Откуда: Харьков, Украина
Сообщений: 1388
ПС: присоединяюсь к поздравлениям с Новым годом. Путь и поздновато, конечно :)
Желаю всем побольше творческих решений, и поменьше ковыряния в старом, особенно чужом ;)
22 янв 14, 13:22    [15451896]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
AntonG
Member

Откуда: Иркутск
Сообщений: 38
Доработал процедуру получения почты, теперь не падает и не виснет при больших входящих письмах
+ GET_MAIL

 PROCEDURE GET_MAIL(mail_id number,lines number default null) IS
  answer varchar2(32767);
  content_bufer varchar2(32767);
  cnt number;
  bytes number;
  status varchar2(25);
  message_body clob;
  hdr_flag boolean;
  hdr_entity varchar2(255);
  hdr_entity_value varchar2(32717);
  boundary varchar2(128);
  part_header_flag boolean:=false;
  any_boundary_found boolean:=false;
  any_boundary_found_close boolean:=false;
 BEGIN
       IF MAIL_PKG.protocol != MAIL_PKG.POP3 THEN
        RAISE_APPLICATION_ERROR(-20000,'This feauture is not realised yet in proto '||MAIL_PKG.protocol);
       END IF;

       CMD(c,'LIST '||mail_id,status,answer); -- get message size
       MAILBOX(mail_id).bytes:=to_number(trim(substr(answer,instr(answer,' '))));

       IF  MAILBOX(mail_id).bytes >= 1048576 THEN
           PDEBUG('BUG: Message '|| mail_id ||' over 1Mb, ' ||  MAILBOX(mail_id).bytes || ' bytes' ,mail_pkg.debug_errors);
       END IF;

       CMD(c,CASE WHEN lines is NULL THEN 'RETR '||mail_id ELSE 'TOP '||mail_id||' 10' END,status,answer); -- read message headers
       BEGIN
         hdr_entity:='';hdr_entity_value:='';
         hdr_flag := true;
         if lines<>0 or lines is null then
            MAILBOX(mail_id).message:='';
            MAILBOX(mail_id).attachments := t_attachments();
         end if;
         dbms_lob.createtemporary(lob_loc => MAILBOX(mail_id).message, cache => true, dur => dbms_lob.call);
         LOOP
             answer :=utl_tcp.get_line(c, TRUE);  -- read result
             EXIT WHEN answer = '.';
             IF answer IS NULL THEN hdr_flag := false; END IF;
             IF hdr_flag THEN
                 IF ascii(substr(answer,0,1)) NOT IN (9,32) THEN
                   hdr_entity := substr(answer,1,instr(answer,':')-1);
                   MAILBOX(mail_id).HDR(hdr_entity):='';
                   hdr_entity_value := substr(answer,instr(answer,':')+2);
                 ELSE
                   hdr_entity_value := substr(answer,2);
                 END IF;

                 PDEBUG('HDR:'|| answer);
                 MAILBOX(mail_id).HDR(hdr_entity):= MAILBOX(mail_id).HDR(hdr_entity)
                                                 || MIME_DECODE(hdr_entity_value);
                 IF hdr_entity = 'Content-Type' THEN
                   if instr(answer,'boundary="')>0 then
                      extract_value(boundary,answer,'boundary');
                   end if;
                 END IF;
             ELSE
                
                 any_boundary_found := false;
                 any_boundary_found_close := false;
                 IF MAILBOX(mail_id).attachments.count>0 THEN
                 FOR incls IN MAILBOX(mail_id).attachments.first .. MAILBOX(mail_id).attachments.last
                 LOOP
                   if answer = '--' || MAILBOX(mail_id).attachments(incls).boundary then
                     any_boundary_found := true;
                   end if;
                   if answer = '--' || MAILBOX(mail_id).attachments(incls).boundary || '--' then
                     any_boundary_found_close := true;
                   end if;
                 END LOOP;
                 END IF;
								 if length(answer)=0 and length(content_bufer)>0 then
                   DBMS_LOB.APPEND ( MAILBOX(mail_id).attachments(MAILBOX(mail_id).attachments.last).content, content_bufer);
				         end if; 
                 if boundary is not null and
                    ( answer = '--' || boundary
                      or
                      any_boundary_found
                    )
                     then
                    part_header_flag:=true;
                    MAILBOX(mail_id).attachments.extend();
                    dbms_lob.createtemporary(lob_loc => MAILBOX(mail_id).attachments(MAILBOX(mail_id).attachments.last).content, cache => true, dur => dbms_lob.call);
                 elsif boundary is not null and
                   (  answer = '--' || boundary || '--'
                     or
                     any_boundary_found_close
                   )
                     then
                       null;
                 elsif part_header_flag and answer is null then
                    part_header_flag:=false;
                 else
                    IF part_header_flag THEN
                       IF ascii(substr(answer,0,1)) NOT IN (9,32) THEN
                          hdr_entity := substr(answer,1,instr(answer,':')-1);
                          MAILBOX(mail_id).attachments(MAILBOX(mail_id).attachments.last).HDR(hdr_entity):='';
                          hdr_entity_value := substr(answer,instr(answer,':')+2);
                       ELSE
                          hdr_entity_value := substr(answer,2);
                       END IF;
                       MAILBOX(mail_id).attachments(MAILBOX(mail_id).attachments.last).HDR(hdr_entity):=
                              MAILBOX(mail_id).attachments(MAILBOX(mail_id).attachments.last).HDR(hdr_entity)
                           || MIME_DECODE(hdr_entity_value);

                       IF hdr_entity = 'Content-Type' THEN
                          extract_value(MAILBOX(mail_id).attachments(MAILBOX(mail_id).attachments.last).boundary,answer,'boundary');
                          extract_value(MAILBOX(mail_id).attachments(MAILBOX(mail_id).attachments.last).charset,answer,'charset');
--                            PDEBUG(MAILBOX(mail_id).includes(MAILBOX(mail_id).includes.last).charset,mail_pkg.debug_messages);
                       ELSIF hdr_entity = 'Content-Transfer-Encoding' THEN
                            MAILBOX(mail_id).attachments(MAILBOX(mail_id).attachments.last).ContentTransferEncoding := hdr_entity_value;
                       END IF;

                    ELSE

                       -- BUG: BIG messages is very slow and prc can get "[SYS/PERM] Fatal error: Lost connection to input stream"
                      -- IF MAILBOX(mail_id).bytes < 1048576 THEN
                         IF MAILBOX(mail_id).attachments.count>0 THEN
                            if length(answer)>0 then
                               if length(content_bufer||answer) >= 32767 then
                                 DBMS_LOB.APPEND ( MAILBOX(mail_id).attachments(MAILBOX(mail_id).attachments.last).content, content_bufer);
                                 content_bufer := PARSE_LINE( answer
                                                             ,MAILBOX(mail_id).attachments(MAILBOX(mail_id).attachments.last).ContentTransferEncoding
                                                             ,MAILBOX(mail_id).attachments(MAILBOX(mail_id).attachments.last).charset);
                               else
                                 content_bufer := content_bufer||PARSE_LINE( answer
                                                                             ,MAILBOX(mail_id).attachments(MAILBOX(mail_id).attachments.last).ContentTransferEncoding
                                                                             ,MAILBOX(mail_id).attachments(MAILBOX(mail_id).attachments.last).charset);
                               end if;  
                            end if;
                         ELSE
                            IF length(answer)>0 THEN
                              DBMS_LOB.APPEND (MAILBOX(mail_id).message,answer);
                            END IF;
                         END IF;
                      -- END IF;

                    END IF;
                    PDEBUG(CASE part_header_flag WHEN TRUE THEN 'H' ELSE 'B' END || '-BODY:'||answer);
                 end if;
             END IF;

         END LOOP;
       EXCEPTION
         WHEN OTHERS THEN
         PDEBUG('ERR: GET MESSAGE ' ||mail_id || ' ERROR ',mail_pkg.debug_errors);
         RAISE;
       END;
       IF MAILBOX(mail_id).HDR.EXISTS('From') THEN
          MAILBOX(mail_id).MailFrom := MAILBOX(mail_id).HDR('From');
       END IF;
       IF MAILBOX(mail_id).HDR.EXISTS('MailTo') THEN
          MAILBOX(mail_id).MailTo := MAILBOX(mail_id).HDR('To');
       END IF;
       IF MAILBOX(mail_id).HDR.EXISTS('Return-Path') THEN
          MAILBOX(mail_id).ReturnPath := MAILBOX(mail_id).HDR('Return-Path');
       END IF;
       IF MAILBOX(mail_id).HDR.EXISTS('Subject') THEN
          MAILBOX(mail_id).Subject := MAILBOX(mail_id).HDR('Subject');
       END IF;
       IF MAILBOX(mail_id).HDR.EXISTS('Date') THEN
          BEGIN
            MAILBOX(mail_id).MailDate := TO_TIMESTAMP_TZ(MAILBOX(mail_id).HDR('Date'),'Dy, DD Mon YYYY HH24:MI:SS TZHTZM','NLS_DATE_LANGUAGE = ''american''');
          EXCEPTION WHEN OTHERS THEN NULL; END;
       END IF;
 END;

31 янв 14, 08:52    [15498207]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
Возможен оффтоп.
Кто-нибудь пытался вставить, скажем, график роста своей зарплаты в рассылаемые письма?
какой процедурой (или на java) создать график, как его сохранить и вставить в письмо (вставка более менее понятна =) )?
6 фев 14, 10:54    [15526960]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
-2-
Member

Откуда:
Сообщений: 12953
with t as (
  select (level-1)/3.141526 x, sin((level-1)/3.141526) y from dual connect by level<=21
)
   , taxis as (
  select round(199*(0-min(x))/(max(x)-min(x))) x, round(99*(0-min(y))/(max(y)-min(y))) y from t
)
   , tscale as (
  select round(199*(x - min(x) over()) / (max(x) over() - min(x) over())) x, 99-round(99*(y - min(y) over()) / (max(y) over() - min(y) over())) y from t
)
select 0.0 r, '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="100">' svgline from dual union all
select 0.1, '<rect width="200" height="100" style="fill: grey; stroke: black;" />'  from dual union all
select 0.2, '<line x1="0" y1="'||y||'" x2="199" y2="'||y||'" style="stroke: blue;"/>
<line x1="'||x||'" y1="0" x2="'||x||'" y2="99" style="stroke: blue;"/>'  from taxis union all
select rownum, '<line x1="'||lag(x,1,x) over(order by x)||'" y1="'||lag(y,1,y) over(order by x)||'" x2="'||x||'" y2="'||y||'" style="stroke: red;"/>' 
from tscale union all
select null, '</svg>' from dual
order by 1 nulls last
;


К сообщению приложен файл (svg.svg - 1Kb) cкачать
6 фев 14, 11:54    [15527345]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
Asmodeus
Member

Откуда: Минск
Сообщений: 521
-2-, замечательно!
З.Ы. Какое, однако, забавное "пи" используется. :-)
6 фев 14, 14:32    [15528768]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
-2-
Member

Откуда:
Сообщений: 12953
Asmodeus
З.Ы. Какое, однако, забавное "пи" используется. :-)
Со школы уже столько "пи" прошло..., что девятка из памяти выпала.
6 фев 14, 14:46    [15528877]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
orawish
Member

Откуда: Гадюкино-2 (City)
Сообщений: 15379
-2-
Asmodeus
З.Ы. Какое, однако, забавное "пи" используется. :-)
Со школы уже столько "пи" прошло..., что девятка из памяти выпала.

acos(-1) надёжнее
6 фев 14, 14:48    [15528891]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
LordOfOrder
Member

Откуда:
Сообщений: 16
chameleon82, во-первых, спасибо Вам большое за этот пакет. Очень сильно помог в работе и сэкономил уйму времени!
Во-вторых, хочу сообщить о проблемах:
1) Отправляем на почту вложением файл xlxs. Я получал такое письмо на yandex-е, и получалось так, что ContentTransferEncoding принимал значение null, поэтому на диск сохранялась всякая херня.
Я не стал особо копаться и заморачиваться и тупо прописал это в коде:
 IF hdr_entity = 'Content-Type' THEN
   extract_value(MAILBOX(mail_id).attachments(MAILBOX(mail_id).attachments.last).boundary,answer,'boundary');                       
   extract_value(MAILBOX(mail_id).attachments(MAILBOX(mail_id).attachments.last).charset,answer,'charset');
------------------- Моя вставка
 IF INSTR(answer, 'APPLICATION') > 0 THEN
   MAILBOX(mail_id).attachments(MAILBOX(mail_id).attachments.last).ContentTransferEncoding := 'base64';
 END IF;
------------------- Моя вставка

Если вы скажете, куда отослать, то я пошлю вам это письмо.

2) Вторая ошибка гораздо серьезнее.

автор
----ALT--pUggPsmc1392604312
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: base64

CgrQodGD0LHRgdC40LTQuNC4INCx0Y7QtNC20LXRgtC90YvQvCDRg9GH0YDQtdC20LTQtdC90LjR
j9C8INC90LAg0YDQtdCw0LvQuNC30LDRhtC40Y4g0LTQvtC/0L7Qu9C90LjRgtC10LvRjNC90YvR
hSDQvNC10YDQvtC/0YDQuNGP0YLQuNC5LCDQvdCw0L/RgNCw0LLQu9C10L3QvdGL0YUg0L3QsCDR
gdC90LjQttC10L3QuNC1INC90LDQv9GA0Y/QttC10L3QvdC+0YHRgtC4INC90LAg0YDRi9C90LrQ
tSDRgtGA0YPQtNCwINGB0YPQsdGK0LXQutGC0L7QsiDQoNCkIC0gOTEwOTMxCi0tIApNaXNoYSBN
aXNoYQ==


Смотрите, кодировка utf-8. Когда код доходит до вызова функции CONVERT при парсинге строки при попытке положить данные в CLOB:
CONVERT(UTL_RAW.cast_to_varchar2(UTL_ENCODE.base64_decode(UTL_RAW.cast_to_raw(
'CgrQodGD0LHRgdC40LTQuNC4INCx0Y7QtNC20LXRgtC90YvQvCDRg9GH0YDQtdC20LTQtdC90LjR'
))), 'CL8MSWIN1251', 'UTF8')

, то происходит ошибка. Потому что идет разрыв в символах. Если убрать в конце 'R' или добавить 'j9' из начала новой строки, то все пройдет хорошо. Сам метод конвертации по-частям ущербен. Нужно сначала собирать все в одну кучу, а потом одной операцией конвертить.
17 фев 14, 12:52    [15576618]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
LordOfOrder
chameleon82, во-первых, спасибо Вам большое за этот пакет. Очень сильно помог в работе и сэкономил уйму времени!

Спасибо )
LordOfOrder
1) Отправляем на почту вложением файл xlxs. Я получал такое письмо на yandex-е, и получалось так, что ContentTransferEncoding принимал значение null

любопытно. но вложение не всегда в base64. чтобы понять причину, нужны все заголовки

LordOfOrder
Если вы скажете, куда отослать, то я пошлю вам это письмо.

приложите заголовки сюда или само письмо во вложении к сообщению на форуме.

LordOfOrder
2) Вторая ошибка гораздо серьезнее.

Да, конвертировать по частям не есть хорошо, но тут ограничение на 32к символов, а вложения зачастую намного больше. Проблема в том, что не все байты символа всегда в строку входят, это, конечно, бага. Создам на гите issue на это.

ПыСы: чтение почты пакетом все еще пока в экспериментальном состоянии :)
17 фев 14, 14:28    [15577291]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
LordOfOrder
Member

Откуда:
Сообщений: 16
1) По первой ошибке - см. Приложение. Я еще раз проверил - да, без моей вставки не работает.
2) Еще одна проблема - на некоторых письмах может возникать ошибка в блоке:
IF ascii(substr(answer,0,1)) NOT IN (9,32) THEN
  hdr_entity := substr(answer,1,instr(answer,':')-1);
  MAILBOX(mail_id).attachments(MAILBOX(mail_id).attachments.last).HDR(hdr_entity):='';                                    
  hdr_entity_value := substr(answer,instr(answer,':')+2);
ELSE 


Вот здесь hdr_entity может принимать значение null, потому что в строке может не находиться символ ":", соответственно возникает ошибка присвоения значения null-ключу. Я тупо обернул инструкцию: nvl(hdr_entity, '?') и не стал заморачиваться. Вот как это может произойти:

автор
MIME-Version: 1.0
Content-Type: multipart/mixed;
boundary="----------0B5176249399AFBB7"

------------0B5176249399AFBB7
Content-Type: text/plain; charset=windows-1251
Content-Transfer-Encoding: quoted-printable

=C7=E4=F0=E0=E2=F1=F2=E2=F3=E9=F2=E5, .



---------- =CF=E5=F0=E5=F1=FB=EB=E0=E5=EC=EE=E5 =EF=E8=F1=FC=EC=EE --------=
--
=CE=F2: =D3=E3=EB=EE=E2 =CC=E8=F5=E0=E8=EB <uglov@minfin-a=
ltai.ru>
=CA: svod@parusaltai.ru
=C0 =F2=E0=EA=E6=E5 =EA: =20
=C2=F0=E5=EC=FF =F1=EE=E7=E4=E0=ED=E8=FF: Fri, 14 Feb 2014 13:16:09 +0=
700
=D2=E5=EC=E0: =C7=E0=FF=E2=EA=E0 =F1=E2=EE=E4=FB =B9140214/2
=CF=F0=E8=EA=F0=E5=EF=EB=E5=ED=ED=FB=E5 =F4=E0=E9=EB=FB: =C7=E0=FF=E2=EA=E0=
.xlsx

=C7=E4=F0=E0=E2=F1=F2=E2=F3=E9=F2=E5, .


Вот на строчке "ltai.ru>" оно и крашится.

К сообщению приложен файл (mail1.txt - 16Kb) cкачать
18 фев 14, 07:14    [15580192]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
LordOfOrder
Member

Откуда:
Сообщений: 16
Если это поможет, то по 2 ошибке письмо:
1) Пересылаемое
2) Приходит на почту на сервисе https://vhost5.sibdc.ru/webmail

Кхм...неужто выходит так, что по строчкам вообще не стоит делать разбор? Или "=" - это знак переноса строки? Тогда Вам придется запилить обработку переноса?
18 фев 14, 07:19    [15580194]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
AntonG
Member

Откуда: Иркутск
Сообщений: 38
Добрый день,
я тоже заинтересован в процессе получения почты, поэтому вот моя исправленная/дополненная версия

переписана процедура get_mail

1. исправлена проблема построчной конвертации
2. добавлена возможность перезаписывать вложения когда в одном почтовом сообщении содержится несколько частей, содержащих одну и ту же информацию например в text/plain и text/html

К сообщению приложен файл (MAIL_PKG.pck - 42Kb) cкачать
18 фев 14, 07:27    [15580200]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
Vadim Romanenko
Привет всем!

Для того, чтоб не испытывать проблем, как у May12, я бы категорически предложил всем переменным типа varchar2 выдать размер с запасом. Например, в текущем варианте под папку отдается 30 символов. Люди, ну чем Вы думаете?? Под имя файла 256, под имя папки - 30 :) Да кто в Оракле трясется сегодня над каждым байтом??? Тем более в пакете, тем более, когда это имя и папка не хранится в БД? Сегодня ОЗУ считается гигабайтами, а не килобайтами!


sys.obj$.name (который Вы видите через all_directories) = varchar2(30) ни больше, ни меньше. Это алиас, а не полный путь, обратите на это внимание
20 фев 14, 06:20    [15595120]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
Bios852
Member

Откуда:
Сообщений: 1
chameleon82,

Помогите. Скопировал пакет, скомпилировал нормально. При попытке отправить письмо все время ругается на utl_smtp.Mail(v_Mail_Conn, sndr.rcptmail); в процедуре send, пишет Syntax error. Почему? Версия Oracle 8 или 9 точно не помню сейчас нет возможности посмотреть.
2 июл 14, 18:05    [16251396]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
jan2ary
Member

Откуда: Киев
Сообщений: 1572
Тут Javamail API упоминался, на всякий случай оставлю это здесь
Sending Mails Through Java Stored Procedure Fails After Database Upgrade to 11.2.0.4 (Doc ID 1631194.1)
8 июл 14, 12:59    [16274669]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
Bios852,

пакет работает на версии оракла 9 и выше
23 июл 14, 13:02    [16346214]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
igor_gar
Member

Откуда:
Сообщений: 3
При использовании пакета с отправкой почты без атача, при вызове пакета возвращает ошибку: ORA-06531: Reference to uninitialized collection. Версия Oracle 11.2.0.4.

Изучение проблемы указало на строки кода:
 type attach_list is table of attach_row;
 attachments attach_list;


Переписание строк на следующие решило проблему:

type attach_list is table of attach_row;
 attachments attach_list := attach_list();
30 июл 14, 15:41    [16377661]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
Egoza
Guest
Добрый день!
У меня Oracle 11.2.0.4. Для кодирования заголовков использую UTL_ENCODE.MIMEHEADER_ENCODE (encoding - base64). При длине заголовка более 46 символов процедура разбивает заголовок на несколько строк, вот только не совсем верно - перед каждой новой частью нет проблема - как результат, почтовый сервер неверно разбирает MIME-заголовoк. Взял процедуру ENCODE из пакета PKG_MAIL - верно разбивается заголовок и почтовый сервер его верно воспринимает. Не смог понять, почему разбиение строки в ENCODE сделано на 24 символа. Разъясните, пожалуйста, почему для типов кодирования base64 и quoted-printable encode выбраны именно такие константы. И может кто знает, как научить работать верно UTL_ENCODE.MIMEHEADER_ENCODE ?
28 сен 14, 14:44    [16630817]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
Egoza, подбиралось экспериментальным путем. Стоит помнить, что длина строки письма не должна превышать 76 символов, в противном случае почтовые клиенты могут неправильно обрабатывать полученный текст
30 сен 14, 11:29    [16637614]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
Egoza
Guest
chameleon82, спасибо за пояснение.
30 сен 14, 13:20    [16638244]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
Snezhanka
Member

Откуда: Россия
Сообщений: 2
почему именно 76 символов? не помню про это ограничение
2 окт 14, 02:52    [16647886]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
Вячеслав Любомудров
Member

Откуда: Владивосток
Сообщений: 17275
Snezhanka
почему именно 76 символов? не помню про это ограничение
Это не совсем ограничение
Скорее правило хорошего тона
http://tools.ietf.org/html/rfc2822#section-2.3
2 окт 14, 03:05    [16647890]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
AG#
Member

Откуда: Российская Федерация
Сообщений: 2305
NO-WS-CTL = %d1-8 / ; US-ASCII control characters
%d11 / ; that do not include the
%d12 / ; carriage return, line feed,
%d14-31 / ; and white space characters
%d127

text = %d1-9 / ; Characters excluding CR and LF
%d11 /
%d12 /
%d14-127 /
obs-text

specials = "(" / ")" / ; Special characters used in
"<" / ">" / ; other parts of the syntax
"[" / "]" /
":" / ";" /
"@" / "\" /
"," / "." /
DQUOTE

No special semantics are attached to these tokens. They are simply
single characters.
2 окт 14, 05:47    [16647957]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
AG#
Member

Откуда: Российская Федерация
Сообщений: 2305
AG#,

No special semantics are attached to these tokens. They are simply
single characters.
2 окт 14, 05:49    [16647958]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
Исправлена ошибка с получателями, стоявшими в копии письма, спасибо пользователю llocust Git
24 ноя 14, 12:46    [16895774]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
May12
Member

Откуда: ТУЛЫП
Сообщений: 877
Ребят, а у вас на группы рассылки нормально письма ходят? у меня ошибка:
 ORA-29279: Постоянная ошибка SMTP: 550 5.1.1 User unknown
17 сен 15, 13:15    [18160507]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
May12, проверьте пользователей в рассылке, такая ошибка возникает, когда ящика одного из пользователей в рассылке не существует.
18 сен 15, 06:16    [18163774]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
6eper
Member

Откуда:
Сообщений: 8
chameleon82,

Пытаюсь подключиться к серверу для получения количества писем:
MAIL_PKG2.SET_MAILSERVER ('server_ip_address');
MAIL_PKG2.SET_AUTH ('mail_user','mail_password');
MAIL_PKG2.MAIL_CONNECT('POP3');

При выполнении процедуры MAIL_CONNECT выдает ошибку:
14:07:22 ORA-20000: -ERR [AUTH] You must use stronger authentication such as AUTH or APOP to connect to this server

Помогите ее обойти, плиз
15 фев 16, 15:14    [18818471]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
Ljucius11
Member

Откуда:
Сообщений: 3
Всех приветствую, есть вопрос, может тут подскажут.
использую пакет UTL_SMTP почта успешно отправляется.
используя функцию Reply := Utl_Smtp.Close_Data(V_Mail_Conn); получаю ИД почтового уведомления которое мне прислал Почтовый сервер.

Вопрос: Как по данному ИД средствами PL/SQL запросить у почтового сервера статус доставки данного уведомления.

Вопросы типо а зачем и кому это нужно прошу не задавать, так как с этим проблема и я лучше промолчу.
Скажу кратко НАДО.

Благодарен за ответ.
25 фев 16, 19:38    [18864375]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
bounce message
Guest
Ljucius11
и я лучше промолчу
поздно метаться, уже сказал.
25 фев 16, 19:46    [18864389]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
Ljucius11
Member

Откуда:
Сообщений: 3
bounce message
Ljucius11
и я лучше промолчу
поздно метаться, уже сказал.


Того требует заказчик
26 фев 16, 06:08    [18865458]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
Ljucius11
Member

Откуда:
Сообщений: 3
Ljucius11
bounce message
пропущено...
поздно метаться, уже сказал.


Того требует заказчик


Тем более что он не умеет настраивать почтовый сервер, приходится делать кастыли
2 мар 16, 09:34    [18885812]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
6eper,

Добрый день. Пока не реализовал (
15 мар 16, 13:40    [18933221]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
fadeevpv
Member

Откуда: Tomsk
Сообщений: 3
chameleon82,

День добрый , подскажите , мне нужно просто отправлять почту по срабатыванию процесса !

хочу попробовать ваш скрипт что мне лучше всего забрать а что убрать ? http://www.sql.ru/forum/1216064-a/apex-4-2-i-otpravka-pochty-iz-prilozheniya

спасибо !
30 май 16, 12:46    [19235669]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
chameleon82
Member

Откуда: Russia, Новосибирск
Сообщений: 251
fadeevpv,
День добрый. Пакет устанавливается и работает независимо. Так что забирайте целиком :)
1 июн 16, 10:04    [19244208]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
blkangel
Member

Откуда:
Сообщений: 1613
chameleon82
fadeevpv,
День добрый. Пакет устанавливается и работает независимо. Так что забирайте целиком :)


Ну как же независимо. Зависит от UTL_SMTP, UTL_TCP. на которые надо дать разрешения. :)
1 июн 16, 10:33    [19244350]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
ikonst
Member

Откуда:
Сообщений: 75
Может быть кому-то пригодиться, ну и мне чтобы не забыть.

Для работы через SSL можно использовать утилиту stunnel.org. MAIL_PKG делает коннект к localhost:1925, stunnel оборачивает его в SSL и отправляет на нужный адрес - smtp.yandex.ru:465.

stunnel.conf:
...
[ssmtp]
accept = 1925
connect = smtp.yandex.ru:465

Настройка stunnel зависит от ОС и требует некоторых действий.
18 авг 16, 15:20    [19558441]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
A_Karetnikov
Member

Откуда:
Сообщений: 8
Всем доброго дня!
Сломал себе голову, мне необходимо отправлять результат запроса на соответствующий email с помощью процедуры в pl/sql
Процедура ниже
procedure unica_sms_report_forward
as 
  p_to           VARCHAR2(30) := 'vasya@yandex.ru;
  p_from         VARCHAR2(30) := 'oracle@yandex.ru';
  p_subject      VARCHAR2(300) := 'Ежедневный отчет';
  p_text_msg     VARCHAR2(50) := 'Сформирован новый отчет';
  p_attach_name  VARCHAR2(50) := 'Отчет по доставленным смс '|| TO_CHAR(SYSDATE, 'DD-MON-YYYY') ||'.xls';
  p_attach_mime  VARCHAR2(200) := 'application/octet-stream';
  p_attach_clob  CLOB := 'Наименование компании'||chr(9)||'Дата формирования'||chr(9)||'Сформированные смс на'||chr(9)||'Доставлено';
  p_smtp_host    VARCHAR2(30):= 'mail.yandex.ru' ; --'192.168.110.230'; -- local database host
  p_smtp_port    NUMBER DEFAULT 25;
  l_mail_conn   UTL_SMTP.connection;
  l_boundary    VARCHAR2(50) := '----=*#abc1234321cba#*=';
  l_step        PLS_INTEGER  := 12000; -- make sure you set a multiple of 3 not higher than 24573

  BEGIN
    siebel.ts_ops.unica_sms_report_created;
    -- запись выгрузки в переменную p_attach_clob
    for x in (select campaign_name||chr(9)||created_dt||chr(9)|| formed_sms||chr(9)|| delivered as str from siebel.unica_sms_report 
               where created_dt > trunc(sysdate) - 30)
    loop
        p_attach_clob := p_attach_clob || chr(13) || x.str;
    end loop;
    p_attach_clob := p_attach_clob || ' ';
    --Подключение к хосту
    l_mail_conn := UTL_SMTP.open_connection(p_smtp_host, p_smtp_port);

    UTL_SMTP.helo(l_mail_conn, p_smtp_host);
    UTL_SMTP.mail(l_mail_conn, p_from);
    UTL_SMTP.rcpt(l_mail_conn, p_to);

    --Наполнение письма
    UTL_SMTP.open_data(l_mail_conn);
    UTL_SMTP.write_raw_data(l_mail_conn, UTL_RAW.cast_to_raw('Date: ' || TO_CHAR(SYSDATE, 'DD-MON-YYYY HH24:MI:SS') || UTL_TCP.crlf));
    UTL_SMTP.write_raw_data(l_mail_conn, UTL_RAW.cast_to_raw('To: ' || p_to || UTL_TCP.crlf));
    UTL_SMTP.write_raw_data(l_mail_conn, UTL_RAW.cast_to_raw('From: ' || p_from || UTL_TCP.crlf));
    UTL_SMTP.write_raw_data(l_mail_conn, UTL_RAW.cast_to_raw('Subject: ' || p_subject || UTL_TCP.crlf));
    UTL_SMTP.write_raw_data(l_mail_conn, UTL_RAW.cast_to_raw('MIME-Version: 1.0' || UTL_TCP.crlf));
    UTL_SMTP.write_raw_data(l_mail_conn, UTL_RAW.cast_to_raw('Content-Type: multipart/mixed; charset="windows-1251"; boundary="' || l_boundary || '"' || UTL_TCP.crlf || UTL_TCP.crlf));

    IF p_text_msg IS NOT NULL THEN
      UTL_SMTP.write_raw_data(l_mail_conn, UTL_RAW.cast_to_raw('--' || l_boundary || UTL_TCP.crlf));
      UTL_SMTP.write_raw_data(l_mail_conn, UTL_RAW.cast_to_raw('Content-Type: text/plain; charset="windows-1251"' || UTL_TCP.crlf || UTL_TCP.crlf));

      UTL_SMTP.write_raw_data(l_mail_conn, UTL_RAW.cast_to_raw( p_text_msg));
      UTL_SMTP.write_raw_data(l_mail_conn, UTL_RAW.cast_to_raw(UTL_TCP.crlf || UTL_TCP.crlf));
    END IF;

    IF p_attach_name IS NOT NULL THEN
      UTL_SMTP.write_raw_data(l_mail_conn, UTL_RAW.cast_to_raw('--' || l_boundary || UTL_TCP.crlf));
      UTL_SMTP.write_raw_data(l_mail_conn, UTL_RAW.cast_to_raw('Content-Type: ' || p_attach_mime || '; name="' || p_attach_name || '"' || UTL_TCP.crlf));
      UTL_SMTP.write_raw_data(l_mail_conn, UTL_RAW.cast_to_raw('Content-Disposition: attachment; filename="' || p_attach_name || '"' || UTL_TCP.crlf || UTL_TCP.crlf));
      
      
      FOR i IN 0 .. TRUNC((DBMS_LOB.getlength(p_attach_clob) - 1)/l_step) LOOP
        UTL_SMTP.write_raw_data(l_mail_conn, UTL_RAW.cast_to_raw(DBMS_LOB.substr(p_attach_clob, l_step, i * l_step + 1)));
      END LOOP;

      UTL_SMTP.write_raw_data(l_mail_conn, UTL_RAW.cast_to_raw(UTL_TCP.crlf || UTL_TCP.crlf));
    END IF;

    UTL_SMTP.write_raw_data(l_mail_conn,UTL_RAW.cast_to_raw( '--' || l_boundary || '--' || UTL_TCP.crlf));
    UTL_SMTP.close_data(l_mail_conn);

    --Отключение от хоста
    UTL_SMTP.quit(l_mail_conn);
  END;


1)Сама отправка проходит успешно ,файл создается и отсылается, но когда я его пытаюсь открыть в excel 2007, то у меня вылетает ошибка о том, что тип формат открываемого файла не совпадает с расширением файла xls, если нажать да, то файл откроется успешно. Если принудительно выставить в наименование файла расширение xlsx, то файл вообще не открывается(переменная p_attach_name ). Пробовал менять значение переменной p_attach_mime :
-application/vnd.ms-excel
-application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
-NULL
Ничего не помогает

2)Данный отчет необходим "большим людям", а они любят смотреть почту в телефонах и айпадах. У нас в организации мобильным клиентом является IBM Verse(не реклама). Так вот в нем файл с xls вообще открыть нельзя, вероятно из-за ошибки в пункте 1
Помогите пожалуйста.
Всем спасибо!
14 окт 16, 17:04    [19782861]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
andreymx
Member

Откуда: Запорожье
Сообщений: 41790
A_Karetnikov

А оракл тут при чём?
14 окт 16, 22:06    [19783915]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
A_Karetnikov
Member

Откуда:
Сообщений: 8
Мне кажется проблема в этом параметре p_attach_mime VARCHAR2(200) := 'application/octet-stream';
Если его правильно подобрать, то можно решить проблему, описанную в пункте 1
17 окт 16, 10:12    [19788678]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
-2-
Member

Откуда:
Сообщений: 12953
A_Karetnikov
Мне кажется
ты преувеличиваешь роль mime_type для твоей ситуации. И в любом случае оракл тут не причем.
17 окт 16, 13:46    [19790168]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
A_Karetnikov
Member

Откуда:
Сообщений: 8
Можно ли формировать файл с расширением xlsx?
17 окт 16, 15:53    [19791081]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
A_Karetnikov
Member

Откуда:
Сообщений: 8
Помогите пожалуйста, возможно текст процедуры написан неверно
20 окт 16, 14:38    [19804864]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
Fogel
Member

Откуда:
Сообщений: 182
A_Karetnikov
Можно ли формировать файл с расширением xlsx?

можно
попроси "больших людей" купить вот это
или сам разберись в xml структуре формата xlsx (а у него именно xml структура) и как оракловые данные заворачивать в xml
20 окт 16, 15:26    [19805081]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
orawish
Member

Откуда: Гадюкино-2 (City)
Сообщений: 15379
A_Karetnikov
Помогите пожалуйста, возможно текст процедуры написан неверно

для начала - вас не смущает незакрытый апостроф в первой строке?
20 окт 16, 15:47    [19805177]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
A_Karetnikov
Member

Откуда:
Сообщений: 8
orawish,

Текст процедуры я правил в рамках сокрытия конфиденциальных данных. На бою у меня все это есть
20 окт 16, 16:21    [19805354]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
A_Karetnikov
Member

Откуда:
Сообщений: 8
При этом, если я сохраню сформированный файл на компьютере, а затем его снова открою и нажму "сохранить как", то предлагает сохранить тип файла как "Текстовые файлы (с разделителями табуляции) (*.txt)"
20 окт 16, 16:30    [19805397]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
dba123
Member

Откуда:
Сообщений: 962
A_Karetnikov,

замени '.xls' на '.csv'
20 окт 16, 16:35    [19805423]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
A_Karetnikov
Member

Откуда:
Сообщений: 8
dba123,

Если я так сделаю у меня все столбцы склеются в один.
21 окт 16, 09:47    [19807245]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
я ни роботъ
Guest
A_Karetnikov
dba123,

Если я так сделаю у меня все столбцы склеются в один.
выложи сюда файл, который получился в результате у получателя
21 окт 16, 09:58    [19807301]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
A_Karetnikov
Member

Откуда:
Сообщений: 8
Решено.
Если вначале файла csv добавить "sep=,"
То происходит разделение на столбцы
21 окт 16, 14:32    [19809358]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
andreymx
Member

Откуда: Запорожье
Сообщений: 41790
как запросить уведомление о прочтении?
Я сам этого не люблю, но клиент запросил

в CDO+c# как-то так:
oMsg.DSNOptions = CDO.CdoDSNOptions.cdoDSNSuccess; //для получения уведомления о доставке и прочтении


в CDO+EWS как-то так:
mail.IsReadReceiptRequested = is_readReceipt;



Как протолкнуть через в utl_http?
5 фев 17, 17:45    [20181741]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
andreymx
Member

Откуда: Запорожье
Сообщений: 41790
andreymx
как запросить уведомление о прочтении?
Я сам этого не люблю, но клиент запросил

в CDO+c# как-то так:
oMsg.DSNOptions = CDO.CdoDSNOptions.cdoDSNSuccess; //для получения уведомления о доставке и прочтении



в CDO+EWS как-то так:
mail.IsReadReceiptRequested = is_readReceipt;




Как протолкнуть через в utl_http?


вроде такое чего-то накропал, и даже работаетSRC PLSQL] IF Confirm_Reading = '1' THEN

utl_smtp.write_data(v_Mail_Conn, 'Disposition-Notification-To: ' || '4' || crlf );

END IF;
[/SRC]
5 фев 17, 19:51    [20181899]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
andreymx
Member

Откуда: Запорожье
Сообщений: 41790
вроде такое чего-то накропал, и даже работает
    IF Confirm_Reading = '1' THEN
    
       utl_smtp.write_data(v_Mail_Conn, 'Disposition-Notification-To: ' || '4' || crlf );
       
    END IF;
5 фев 17, 19:51    [20181901]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
trace.log
Guest
Вопрос знактокам:
Как на выходе получить файл с нижним подчеркиванием??
Вот кусок кода:
'REPORT_' || TO_CHAR (date_to + 1, 'rrrrmmdd') || '.html',

Но на почту приходит файл без '_', почему? куда смотреть?
15 фев 17, 11:10    [20213155]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
trace.log
Guest
Уже все возможное пересмотрел и все равно приходит в почте файл: REPORT 20170215.html
Неужели почтовик съедает этот символ?
15 фев 17, 11:49    [20213334]     Ответить | Цитировать Сообщить модератору
 Re: Передача письма с вложением. Готовое решение  [new]
PsyDiamond
Member

Откуда:
Сообщений: 97
вопрос к знатокам (хотя может ответ всё же лежит на поверхности)

вот есть отправка blob в качестве вложения. отчего зависит время прикрепления блоба?

а-ля

/* Содержимое файла */
		FOR i IN 0..TRUNC( (DBMS_LOB.getlength(p_bFile) - 1) / n_Step) LOOP
			UTL_SMTP.write_data(
				t_Mail_Conn,
				UTL_RAW.cast_to_varchar2(UTL_ENCODE.base64_encode(DBMS_LOB.substr(
					p_bFile,
					n_Step,
					i * n_Step + 1
				) ) )
			);
		END LOOP;

n_Step CONSTANT PLS_INTEGER := 12000;
попадаются решения такого плана, а так же с буфером от 57 до 500 скажем.

если я имею файл весом 500кб. процедура прикрепления занимает около 15 секунд
тут дело в SMTP сервере, что он медленно кушает raw или же в этом алгоритме?

хотя вот через пакет sf_timer замерял время исполнения - показывает: Elapsed CPU : ,01 seconds.
31 июл 17, 16:04    [20688808]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: 1 2 3 4 5 6 7 8 9 10 11      [все]
Все форумы / Oracle Ответить