powered by simpleCommunicator - 2.0.29     © 2024 Programmizd 02
Map
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Передача письма с вложением. Готовое решение
274 сообщений из 274, показаны все 11 страниц
Передача письма с вложением. Готовое решение
    #36426166
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В долгих поисках рабочего решения так и не смог найти ничего ценного.
Пришлось почитать RFC и написать свое. Надеюсь кому-нибудь пригодится.
Пакет позволяет добавлять несколько вложений, что немаловажно - так это включая бинарники.
Возможно, кто-нибудь в благодарность поможет мне усовершенствовать пакет такими вещами как авторизация, или оптимизация. Пользуйтесь ;)

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
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;
/

...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36427233
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Доработал пакет, убрал лишнее, сделал разбор входящих емайлов (можно отправлять на несколько емайлов), добавил приоритет письма, добавил авторизацию. Сделал необязательным адрес отправителя (по умолчанию mail@имя_сервера).

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
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;
/

...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36496417
comphead
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chameleon82,

спс )
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36496433
tesaq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
это ох какое спсб
------------- свЕдение данных в таблицу уже есть СЕКРЕТНО ---
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36509635
comphead
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chameleon82,

Кстати, в пакете решена проблема того что тело сообщения в UTL_SMTP должно быть не больше 32K?
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36555030
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
compheadchameleon82,

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

Кстати не проверял ) Я тут еще подладил пакет на длинные названия в заголовке. Проверю, если что исправлю, обновлю пост :)
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36555646
Ura!
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Правильно понимаю, что файлы для атачментов должны лежать на сервере?
И ещё вопрос, цифровой подписью не баловались? т.е. перед отправкой письма подписать его цифровой подписью.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36562342
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ura!Правильно понимаю, что файлы для атачментов должны лежать на сервере?
И ещё вопрос, цифровой подписью не баловались? т.е. перед отправкой письма подписать его цифровой подписью.
Да. Файлы должны быть на сервере в одной из директорий select * from all_directories, туда их при необходимости можно скопировать.
Размер и количество отправляемых файлов неограничены (ну по крайней мере можно отправить сразу несколько картинок по несколько мегабайт или несколько больших отчетов одновременно).
Цифровая подпись, это чтото интересное. Сомневаюсь, что здесь такое возможно, т.к. письмо отдается смтп серверу последовательно (хотя если его сначала сохранить в blob, то может и получится). Хотя если сможете доработать пакет, было бы интересно посмотреть на реализацию :)
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36640886
aure
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
chameleon82В долгих поисках рабочего решения так и не смог найти ничего ценного.
Пришлось почитать RFC и написать свое. Надеюсь кому-нибудь пригодится.
Пакет позволяет добавлять несколько вложений, что немаловажно - так это включая бинарники.
Возможно, кто-нибудь в благодарность поможет мне усовершенствовать пакет такими вещами как авторизация, или оптимизация. Пользуйтесь ;)
[/src]

Спасибо! ;)
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36643001
d.nemolchev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chameleon82,

а JavaMail чем Вас не устроил?
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36643004
d.nemolchev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36643122
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сразу можно отметить, что хардкодить в такие пакеты ansi1251 - не очень разумная идея.
Даже если Вы не верите что Ваше детище пригодится кому-нибудь в просвещенной Европе, то подумйте хотя бы о мультиязычных текстах в рамках таможенного союза :)
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36648158
IgorD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chameleon82 - СПАСИБО!

Внес незначительные изменение в авторизацию в фрагменте кода, добавив exit
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
    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' встречалась дважды, что вызывало ошибку при повторной авторизации. Еще планирую добавить к пакету таблицу лог, в которой писать отправлено/не отравлено сообщение, когда и т.п. Нужно для автоматической работы в джобах и т.п.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36648282
dba123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chameleon82,

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

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

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

где ххх может быть счетчиком, уникальным идентификатором, цифровой сверткой/подписью и т.д.
и тебе учет отправленных и сормовцам метки :)
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36649119
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
d.nemolchevchameleon82,

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


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

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

IgorDchameleon82 - СПАСИБО!

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

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

dba123chameleon82,

еще предложение - менять имена границ подразделов(boundary)
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36649138
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
dba123chameleon82,

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

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

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

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

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

---

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

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
346.
347.
348.
349.
350.
351.
352.
353.
354.
355.
356.
357.
358.
359.
360.
361.
362.
363.
364.
365.
366.
367.
368.
369.
370.
371.
372.
373.
374.
375.
376.
377.
378.
379.
380.
381.
382.
383.
384.
385.
386.
387.
388.
389.
390.
391.
392.
393.
394.
395.
396.
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;
/
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36674137
_Ildar_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Очень интересное решение.
У меня размер сообщения больше 32Кб?

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

Спасибо!
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36674151
вопросец
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
у меня всегда возникает вопрос. зачем тулить этот левый функцианал. и каким то диким извратом его реализовывать. не лучше ли потратив гораздо меньше времени по быренькому склепать службу/демон или задание шедулера/крона которое выколупает из БД необходимые данные и разошлет там чего-то. тем более что такие рассыльщики имеют свойство расползаться до монстров с тяжелой логикой.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36674164
SQL*Plus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вопросецу меня всегда возникает вопрос. зачем тулить этот левый функцианал. и каким то диким извратом его реализовывать. не лучше ли потратив гораздо меньше времени по быренькому склепать службу/демон или задание шедулера/крона которое выколупает из БД необходимые данные и разошлет там чего-то. тем более что такие рассыльщики имеют свойство расползаться до монстров с тяжелой логикой.Это не "левый функционал".
Это нормальный подход программиста Oracle Database использовать штатные возможности Oracle Database.
Для этого требуется только хорошее знание PL/SQL и предлагаемых для него штатных пакетов.

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

Знаешь PL/SQL - пользуйся им. PL/SQL хватает практически для всего.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36674179
_Ildar_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вопросецу меня всегда возникает вопрос. зачем тулить этот левый функцианал. и каким то диким извратом его реализовывать. не лучше ли потратив гораздо меньше времени по быренькому склепать службу/демон или задание шедулера/крона которое выколупает из БД необходимые данные и разошлет там чего-то. тем более что такие рассыльщики имеют свойство расползаться до монстров с тяжелой логикой.

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

HELP!!!! Помогите!
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36674187
вопросец
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Ildar_,

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

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

---

впринципе мысльвысказавшихся я понял.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36674201
_Ildar_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вопросец_Ildar_,
чтобы x86_32 прога жила под x86_64 нужен клиент x86_32

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

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

Не повезло. От такого невезения и ищу решение.
Обойти бы это ограничение по размеру тела письма и все было бы ОК!
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36674231
вопросец
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Ildar_,

не правда ваша. клиент x86_32 работает под x86_64. (Oracle Client)
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36674236
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Ildar_Обойти бы это ограничение по размеру тела письма и все было бы ОК!
Шлите письма html-аттачем, как поступают все современные спамеры :)
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36675233
_Ildar_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymous_Ildar_Обойти бы это ограничение по размеру тела письма и все было бы ОК!
Шлите письма html-аттачем, как поступают все современные спамеры :)
Это мысль. Надо попробовать.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36704154
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
_Ildar_andrey_anonymous_Ildar_Обойти бы это ограничение по размеру тела письма и все было бы ОК!
Шлите письма html-аттачем, как поступают все современные спамеры :)
Это мысль. Надо попробовать.
Все верно, создаете аттач, делаете его типом html или txt, прикрепляете первым, затем остальные атачи. Работает безотказно. Я таким образом посылал хтмлки с картинками.
Еще, если позволите, вопрос. В каком типе переменной у Вас хранится письмо такого размера? В Clob?
По идее можно дописать пакет, на вход подавая CLOB, т.е. два метода SEND, один с варчар, второй с клоб, кому как удобнее )
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36708919
s_elected
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chameleon82,

Автору выражаю огромную благодарность !
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36710052
Фотография suPPLer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chameleon82Вот моя последняя версия )

Код: plaintext
1.
2.
3.
4.
5.
6.
...
    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. Получите:
Код: plaintext
555 5.5.2 Syntax error.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36835740
Glum1111
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
автору огромное спасибо!
давно хотел разобраться с этой темой, но как всегда руки не доходили.
доработал для blob и пошагового заполнения текста сообщения, работает действительно безотказно!

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

буду благодарен любой полезной информации
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36840989
stalker_cop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Всем привет!
Если кому интересно могу отписать как отправить вложение больше чем 32К!
Прикол заключается в том что необходимо закодировать в base64 blob
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36841076
stalker_cop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Используйте следующие процедуры для кодирования и декодирования в 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}
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36841079
stalker_cop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
 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;
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36854393
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Glum1111 автору огромное спасибо!
давно хотел разобраться с этой темой, но как всегда руки не доходили.
доработал для blob и пошагового заполнения текста сообщения, работает действительно безотказно!


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

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

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

Если протокол открытый, то можно, хотя с почтой мне кажется здесь мало общего. Можно также уведомления слать в icq, тут только проблема в том, что вроде никто еще не делал заготовок для работы с протоколом оскар на оракле, но вот на пхп очень много поделок, например http://wip.asminog.com, поэтому у кого есть силы и желание, можете переложить код на оракл, было бы клево.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36854394
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
stalker_copВсем привет!
Если кому интересно могу отписать как отправить вложение больше чем 32К!
Прикол заключается в том что необходимо закодировать в base64 blob
Спасибо за код. А Вы могли бы привести пример работы с Вашим кодом? Я так понял изначальный блоб должен храниться в бд? Как вариант в таком случае можно блоб сохранить во временный файл, тогда пакет его скушает без особых проблем.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36854607
Автору для размышлений.
Бинарники и архивы содержат специфичные символы (например, с кодом 0).
Естественно, данный пакет работать с ними не будут.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36854660
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ПредлагающийАвтору для размышлений.
Бинарники и архивы содержат специфичные символы (например, с кодом 0).
Естественно, данный пакет работать с ними не будут.
Прикрепляемые файлы переводятся в base64, в чем проблема то? Все работает, бинарники и архивы отправляются без проблем.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36861562
stalker_cop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
chameleon82stalker_copВсем привет!
Если кому интересно могу отписать как отправить вложение больше чем 32К!
Прикол заключается в том что необходимо закодировать в base64 blob
Спасибо за код. А Вы могли бы привести пример работы с Вашим кодом? Я так понял изначальный блоб должен храниться в бд? Как вариант в таком случае можно блоб сохранить во временный файл, тогда пакет его скушает без особых проблем.

Всем привет
Я просто предоставил три процедурки которые кодируют и раскодируют блоб в/из base64. В последнем варианте отправки писем отредактировать вызов utl_smtp.write_raw_data(v_Mail_Conn, UTL_ENCODE.base64_encode(vRAW)); На то что я представил (но не в лоб там начитка из файла для начала файл в blob а потом нарезать на кусочки и отправить)
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36869516
iceFR
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Всем привет.

Скажите, а как обстоят дела с отправкой в русской кодировке? пробовал варианты типа:
Код: plaintext
 'content-type: text/plain; charset="koi8-r"'
и прочие варианты кодировок, но ничего из этого путного не вышло.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36870240
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
iceFRпробовал варианты типа:
Код: plaintext
 'content-type: text/plain; charset="koi8-r"'
и прочие варианты кодировок, но ничего из этого путного не вышло.А то, что вы отправляете действительно в koi8-r или вы наивно полагаете, что "кто-то" перекодирует отправляемое из неизвестно чего в то, что нужно?
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36882098
longman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Друзья! пытаюсь воспользоваться предложенным "готовым решением".
Сервер БД: Solaris
СУБД: Oracle 9ir2
Цель: отправлять почту c вложениями (txt, pdf, xls, doc), взятыми из таблицы БД (blob).
При этом сначала вычитываю необходимые файлы в каталог на файловой системе сервера БД. Для этого дописал пакет процедурой (код взят из инета.. неоднократно фигурирует, одно что изменил режим работы utl_file.fopen с WB на W ):

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
-------------------------------------------------------------------------------------------------------
-- 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
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36882162
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
longman,

Возможно utl_file пользуется функциями stdio с контролем utf8. Не все комбинации допустимы при записи текстовыми функциями. На 11g utl_file.fopen имеет параметр open_mode => 'wb'.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36882207
Фотография env
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
longman,

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

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

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

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
 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

Чтобы избежать этой ошибки, запись следует производить в файл, открываемый как двоичный, и в коде формировать окончания строк
Код: plaintext
1.
2.
3.
4.
5.
 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));
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36882214
longman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
-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? кто подскажет?
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36882223
Фотография env
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Возможно лучше будет просто не заморачиваться с файлами, и формировать вложения напрямую из блобов.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36882291
longman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
env,
а несколько подробнее?
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36882453
Фотография env
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
longman,

пожалуйста
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36882460
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
longman,

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

Запись лоба без выкладки в файловую систему - первый пост, просто вместо dbms_lob.fileopen(bfile) -> dbms_lob.open(blob)
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36882688
stalker_cop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А зачем тебе вообще BLOB записывать на файловую систему?
В данном случаи тебе нужно BLOB просто перекодировать в base64
в данном топике есть все необходимое чтоб переделать "готовое решение" под себя.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36882772
longman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
-2- , ничего перезапустить не могу, т.к. БД производственная и мной не управляется)
stalker_cop , переписал код первого поста, а точнее добавил получение Blob на уровне процедуры Send. Всё получилось как нельзя лучше! сейчас опробую пакетные вложения.. на одном файле всё отправилось и доставилось! Спасибо за мысль! Кстати и env так же высказываю благодарность..
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36888521
longman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
и снова здравствуйте! ситуация такова) всё отправляется, практически все требования реализованы.. но при получении письмо содержит порцию кракозябров.. по одной на каждый вложенный файл.. причём на некоторых веб-почтовиках они отображаются, на некоторых нет.. в The Bat! также присутствуют.. (оттуда скриншот не делал.. если нужно - сделаю) во вложении к посту скриншот с почты Mail.ru и Gmail.com .. кто в курсе природы этих символов?
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36888523
longman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
файл не вложился в предыд. посте..
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36888587
longman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
вот скрин с The Bat! на вкладке с файлом doc до 10 символов-кракозябров
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36889706
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
longmanвот скрин с The Bat! на вкладке с файлом doc до 10 символов-кракозябровPDF это такой "почти текст" и на ваших скриншотах это хорошо видно.
В чём проблема-то?
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36889767
longman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
отвечаю сам себе) чтоб подобных лишних вещиц не было, надо в поле Content-Type при формировании письма, а точнее секции вложений необходимо указать не стандартный text/plain ( text/html ), а что-то типа APPLICATION/MSWORD для doc -ов, APPLICATION/PDF для pdf -ов.. вот как бы и всё решение.. также реализовал использование HTML -файла вместо текстового body письма (понятно, что можно просто в body передать теги, но конечный пользователь такими знаниями увы не владеет).. в целом ничего сложного, кому нужно спрашивайте.. всем спасибо..
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36890282
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
longmanотвечаю сам себе) чтоб подобных лишних вещиц не было, надо в поле Content-TypeНадо "щитильнее" курить первоисточники. RFC2045-RFC2049 - в данном случае.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36892184
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Всем спасибо за подсказки.
Я в свою очередь обновил пакет, добавил возможность вставлять блобы (из базы или сформированные вручную).
Выкладываю обновленную версию целиком:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
346.
347.
348.
349.
350.
351.
352.
353.
354.
355.
356.
357.
358.
359.
360.
361.
362.
363.
364.
365.
366.
367.
368.
369.
370.
371.
372.
373.
374.
375.
376.
377.
378.
379.
380.
381.
382.
383.
384.
385.
386.
387.
388.
389.
390.
391.
392.
393.
394.
395.
396.
397.
398.
399.
400.
401.
402.
403.
404.
405.
406.
407.
408.
409.
410.
411.
412.
413.
414.
415.
416.
417.
418.
419.
420.
421.
422.
423.
424.
425.
426.
427.
428.
429.
430.
431.
432.
433.
434.
435.
436.
437.
438.
439.
440.
441.
442.
443.
444.
445.
446.
447.
448.
449.
450.
451.
452.
453.
454.
455.
456.
457.
458.
459.
460.
461.
462.
463.
464.
465.
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;
/
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36898296
uranic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Подскажите в какую сторону копать, чтобы прикрутить pop3 аутентификацию?
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36898314
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uranicПодскажите в какую сторону копать, чтобы прикрутить pop3 аутентификацию?"POP before SMTP", если уж быть точным.
Копать, как я понимаю, в сторону какого-нибудь UTL_TCP. Если, конечно, нет никакого UTL_POP3 :)
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36979794
Uncle Tola
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Огромное Спасибо за Пакет!

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

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
 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 ?
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36979828
Охрименко
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот мое решение :) Тоже много искал, гуглил, исправлял под себя. В письме выглядит немного странно, а именно не могу расшифровать как просто перевести строку. оно либо тулит весь текст в одну строку без переносов, либо вставляет пустую строку. Я выбрал вариант с пустой строкой. Больше 32К возможно. Текст без вложений. Это из джоба генерируется если есть джобы у которых BROKEN='Y' или FAILURES>0. Редактируйте по своему усмотрению.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
/* 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;
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36982498
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Uncle TolaОгромное Спасибо за Пакет!

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

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

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

Быстрый фикс
Найдите в тексте пакета эти строки (в разделе добавления атачей при отправке письма)
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
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 );
и замените вот на это:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
          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. Если необходимо, поправьте в куске кода выше. Отпишитесь, пожалуйста, получилось или нет. Если все получится, то доработаю пакет под это
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #36982550
Uncle Tola
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
chameleon82,

Спасибо!
Под MS Outlook 2007 все нормально.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #37016498
Uncle Tola
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте!

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

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

Заголовок на русском языке нормально обрабатывается, одноко русские символы в теле он чистит :)
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #37016678
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Uncle Tola,

Стоит уточнить версию БД - может все эти испражнения с самописьками и не нужны.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #37016701
Uncle Tola
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
9.2.0.8
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #37017697
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
попробуйте формировать blob в кодировке utf-8, соответственно при отправке кодировку атачмента указывать тоже utf-8. Должно работать.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #37018994
Uncle Tola
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
chameleon82попробуйте формировать blob в кодировке utf-8, соответственно при отправке кодировку атачмента указывать тоже utf-8. Должно работать.

Спасибо.

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

vText := Convert(vMailText, 'UTF8');
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #37198356
wellvk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Всех приветствую, скажите, а в само тело письма можно вставить картинку(*.jpeg), например в кодировки Base64?, не вложенный файл а картинку. Попробовал через bfile, приходит
2F396A2F34414151536B5A4A526741424151454159414267414...
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #37199262
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
wellvkВсех приветствую, скажите, а в само тело письма можно вставить картинку(*.jpeg), например в кодировки Base64?, не вложенный файл а картинку. Попробовал через bfile, приходит
2F396A2F34414151536B5A4A526741424151454159414267414...

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

Для вставки картинки в текст нужно делать следующее: формат письма html , сначала делаем вложение картинки, имя файла даем например my_image.jpg (имя файла, которое должно прийти в письме), затем в теле письма пишем хтмл-код примерно такой:
Код: plaintext
1.
2.
<h1>Письмо с картинкой</h2>
<img src="my_image.jpg">
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #37199266
wellvk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chameleon82, тоесть, если даже картинку перевести в base64, почта(почтовые клиенты) не смогут интерпретировать её?!(жаль, идея была хорошая).
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #37199278
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
wellvk, Если спецификация позволяет вкладывать файл вместо тела письма, то можно. К сожалению,я не изучал этот вопрос в спецификациях, попробуйте поправить пакет.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #37199287
мимо шел
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
wellvk,

<img src="data:image/gif;base64,R0lGODlhDwAPAJECAAAAAP//AAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFCgACACwAAAAADwAPAAAENFBICWqdWNTA+cVAJ3pTOI4A5ZnB1mpebM7sKbr2Xectbf0kH/AFW1k6KVUuWdp9MppfJgIAIfkEBQoAAgAsAwADAAkABgAABBNQACDqlCFQkHkNAhhWZGmWU6pGADs%3D">
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #37211810
TrueRus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Дата формируется не по стандарту RFC2822. Из-за этого некоторые клиенты отпраляют письма в нежелатеьную почту

Код: plaintext
1.
2.
3.
to_char(cast (date$d as timestamp with time zone),
                 'Dy, DD Mon YYYY hh24:mi:ss TZHTZM',
                 'NLS_DATE_LANGUAGE = ''american''');
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #37212096
-2-Uncle Tola,

Стоит уточнить версию БД - может все эти испражнения с самописьками и не нужны.
А что, в 11g есть готовое решение ?
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #37212146
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
проходя_мимо,

Для больше 32к нет, почти. Есть уже загруженный в сиса пакет javax.mail.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #37264576
_Ildar_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Ildar_,

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

Спасибо!
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #37266493
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
_Ildar__Ildar_,

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

Спасибо!

С exchange не работал, но по идее если авторизация smtp должно работать:
Код: plaintext
1.
2.
3.
4.
 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;
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #37612568
andreymx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chameleon82Всем спасибо за подсказки.
Я в свою очередь обновил пакет, добавил возможность вставлять блобы (из базы или сформированные вручную).
Выкладываю обновленную версию целиком:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
...
 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.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #37810424
bgrena
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
chameleon82.. свою очередь обновил пакет, добавил возможность вставлять блобы (из базы или сформированные вручную).
Выкладываю обновленную версию целиком:

Спасибо за превосходный пакет. Получил удовольствие. Мне не хватает только переходника
от внешних файлов (OS) к блобам
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #37810970
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
bgrenaСпасибо за превосходный пакет. Получил удовольствие. Мне не хватает только переходника
от внешних файлов (OS) к блобам

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



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



Если шаблоны писем храните в файлах, запихать их в блоб тоже несложно:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
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;
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #37811053
sinitsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
chameleon82,

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

от себя могу сказать, есть у нас похожее решение на перле ( не для базы ),
теги тоже "руками" проставляются, иногда письма режут фильтры безопасников,
происходит потому, что теги "нестандартные",
т.е. они соответствуют rfc, но фильтры заточены под outlook.
т.е. в письмо надо вставлять не нужные теги чтобы оно было похоже
на outlook'овское, во всяком случае у нас тут.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #37811095
Фотография Ден
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вот уже готовый пример на java, гдето скачал, отлично работает
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #37811101
Фотография Ден
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #37811106
Фотография Ден
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #37881828
andreymx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
заменили
Код: plsql
1.
    utl_smtp.write_data(v_Mail_Conn, 'Date: ' || TO_CHAR(SYSDATE,     'Dy, DD Mon YYYY hh24:mi:ss',       'NLS_DATE_LANGUAGE = ''american''') || crlf);


на
Код: plsql
1.
    utl_smtp.write_data(v_Mail_Conn, 'Date: ' || TO_CHAR(SYSTIMESTAMP,'Dy, DD Mon YYYY HH24:MI:SS TZHTZM','NLS_DATE_LANGUAGE = ''american''') || crlf);

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

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
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;

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



Код можно подогнать под свой пакет.
Сам его собирал по кусочкам :)
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #37936540
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В пакете уже есть эта возможность (т.е. отправлять неограниченное число файлов over 32kb)
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #37952235
seregaLOKI
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
chameleon82, возникла такая проблема. Есть необходимости передать в mesage текст более 32к символов. Использую CLOB, база имеет настройку NLS_CHARACTERSET CL8MSWIN1251. При конверте русских символов в UTF8 в разделе --Message мы на выходе получаем бред.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #37953686
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Обновил пакет, message теперь clob, поэтому если формировать текст размером больше 32кб без вложений, проблем не должно возникнуть, заодно пофиксил некоторые баги, спасибо andreymx.

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
346.
347.
348.
349.
350.
351.
352.
353.
354.
355.
356.
357.
358.
359.
360.
361.
362.
363.
364.
365.
366.
367.
368.
369.
370.
371.
372.
373.
374.
375.
376.
377.
378.
379.
380.
381.
382.
383.
384.
385.
386.
387.
388.
389.
390.
391.
392.
393.
394.
395.
396.
397.
398.
399.
400.
401.
402.
403.
404.
405.
406.
407.
408.
409.
410.
411.
412.
413.
414.
415.
416.
417.
418.
419.
420.
421.
422.
423.
424.
425.
426.
427.
428.
429.
430.
431.
432.
433.
434.
435.
436.
437.
438.
439.
440.
441.
442.
443.
444.
445.
446.
447.
448.
449.
450.
451.
452.
453.
454.
455.
456.
457.
458.
459.
460.
461.
462.
463.
464.
465.
466.
467.
468.
469.
470.
471.
472.
473.
474.
475.
476.
477.
478.
479.
480.
481.
482.
483.
484.
485.
486.
487.
488.
489.
490.
491.
492.
493.
494.
495.
496.
497.
498.
499.
500.
501.
502.
503.
504.
505.
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;
/
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #37953704
seregaLOKI
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
chameleon82,

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

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

Пример работы с получением почты:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
 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;       
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #37960275
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
И, собственно, новая версия пакета.
Принимаю ваши замечания и предложения :)


Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
346.
347.
348.
349.
350.
351.
352.
353.
354.
355.
356.
357.
358.
359.
360.
361.
362.
363.
364.
365.
366.
367.
368.
369.
370.
371.
372.
373.
374.
375.
376.
377.
378.
379.
380.
381.
382.
383.
384.
385.
386.
387.
388.
389.
390.
391.
392.
393.
394.
395.
396.
397.
398.
399.
400.
401.
402.
403.
404.
405.
406.
407.
408.
409.
410.
411.
412.
413.
414.
415.
416.
417.
418.
419.
420.
421.
422.
423.
424.
425.
426.
427.
428.
429.
430.
431.
432.
433.
434.
435.
436.
437.
438.
439.
440.
441.
442.
443.
444.
445.
446.
447.
448.
449.
450.
451.
452.
453.
454.
455.
456.
457.
458.
459.
460.
461.
462.
463.
464.
465.
466.
467.
468.
469.
470.
471.
472.
473.
474.
475.
476.
477.
478.
479.
480.
481.
482.
483.
484.
485.
486.
487.
488.
489.
490.
491.
492.
493.
494.
495.
496.
497.
498.
499.
500.
501.
502.
503.
504.
505.
506.
507.
508.
509.
510.
511.
512.
513.
514.
515.
516.
517.
518.
519.
520.
521.
522.
523.
524.
525.
526.
527.
528.
529.
530.
531.
532.
533.
534.
535.
536.
537.
538.
539.
540.
541.
542.
543.
544.
545.
546.
547.
548.
549.
550.
551.
552.
553.
554.
555.
556.
557.
558.
559.
560.
561.
562.
563.
564.
565.
566.
567.
568.
569.
570.
571.
572.
573.
574.
575.
576.
577.
578.
579.
580.
581.
582.
583.
584.
585.
586.
587.
588.
589.
590.
591.
592.
593.
594.
595.
596.
597.
598.
599.
600.
601.
602.
603.
604.
605.
606.
607.
608.
609.
610.
611.
612.
613.
614.
615.
616.
617.
618.
619.
620.
621.
622.
623.
624.
625.
626.
627.
628.
629.
630.
631.
632.
633.
634.
635.
636.
637.
638.
639.
640.
641.
642.
643.
644.
645.
646.
647.
648.
649.
650.
651.
652.
653.
654.
655.
656.
657.
658.
659.
660.
661.
662.
663.
664.
665.
666.
667.
668.
669.
670.
671.
672.
673.
674.
675.
676.
677.
678.
679.
680.
681.
682.
683.
684.
685.
686.
687.
688.
689.
690.
691.
692.
693.
694.
695.
696.
697.
698.
699.
700.
701.
702.
703.
704.
705.
706.
707.
708.
709.
710.
711.
712.
713.
714.
715.
716.
717.
718.
719.
720.
721.
722.
723.
724.
725.
726.
727.
728.
729.
730.
731.
732.
733.
734.
735.
736.
737.
738.
739.
740.
741.
742.
743.
744.
745.
746.
747.
748.
749.
750.
751.
752.
753.
754.
755.
756.
757.
758.
759.
760.
761.
762.
763.
764.
765.
766.
767.
768.
769.
770.
771.
772.
773.
774.
775.
776.
777.
778.
779.
780.
781.
782.
783.
784.
785.
786.
787.
788.
789.
790.
791.
792.
793.
794.
795.
796.
797.
798.
799.
800.
801.
802.
803.
804.
805.
806.
807.
808.
809.
810.
811.
812.
813.
814.
815.
816.
817.
818.
819.
820.
821.
822.
823.
824.
825.
826.
827.
828.
829.
830.
831.
832.
833.
834.
835.
836.
837.
838.
839.
840.
841.
842.
843.
844.
845.
846.
847.
848.
849.
850.
851.
852.
853.
854.
855.
856.
857.
858.
859.
860.
861.
862.
863.
864.
865.
866.
867.
868.
869.
870.
871.
872.
873.
874.
875.
876.
877.
878.
879.
880.
881.
882.
883.
884.
885.
886.
887.
888.
889.
890.
891.
892.
893.
894.
895.
896.
897.
898.
899.
900.
901.
902.
903.
904.
905.
906.
907.
908.
909.
910.
911.
912.
913.
914.
915.
916.
917.
918.
919.
920.
921.
922.
923.
924.
925.
926.
927.
928.
929.
930.
931.
932.
933.
934.
935.
936.
937.
938.
939.
940.
941.
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;
/
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #37960289
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chameleon82- Получить вложения! (все вложения представлены как CLOB)может быть сейчас с этим получше, во времена outlook express проблем хватало, особенно с переадресованными между разными почтовыми клиентами писем. проблемой было даже понять, что из миме-партийцев является телом самого сообщения.

Java Mail API вполне стабильное решение.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #37960323
SvDev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Для сравнения

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

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)
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38027352
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chameleon82, спасибо. почитала, но не уловила.
Может Ваш пакет отправлять таблицы в теле письма?
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38027576
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Какие именно таблицы? Не совсем понятно, о чем идет речь. Если о таблицах БД - то, разумеется, пакет для этого и создавался. Формат данных Вы должны подготовить сами. В принципе, пакет может отправлять все что угодно, Вам необходимо только подготовить необходимые данные в файл или в клоб и вложить в апи. Я лично без проблем отправляю через пакет генерируемые в pl/sql xml-excel файлы (несколько штук по 10-15 мегабайт каждое в одном письме) плюс из файловой системы подтягиваю логотип для подписи в письме. Если Вам необходимо архивировать, то сначала сохраните данные в файл, затем заархивируйте (решения можно поискать на форуме) и потом приложите в пакет.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38027599
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
-2-может быть сейчас с этим получше, во времена outlook express проблем хватало, особенно с переадресованными между разными почтовыми клиентами писем. проблемой было даже понять, что из миме-партийцев является телом самого сообщения.


Главная цель, для которой был написан прием почты - возможность скармливать ораклу массивы данных. В принципе, найти в партициях то, что нужно зная что искать - не самая сложная задача )
На моем примере это массовая обработка транзакций ) почтовый сервер хорошо логгирует историю действий ленивых бухгалтеров ) Допустим, мы выгрузили массив данных в 1000 транзакций (в екселе бухам намного проще почему-то делать это), затем бухгалтер отправляет файл на почту ораклу, задав специальный заголовок, оракл получил письмо, обработал, выслал на обратный адрес результат загрузки с указанием ошибок. Ну вот сложно бухам через форму прикладывать файл или грузить через фтп )
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38028223
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chameleon82,

имелось в виду небольшие таблицы-отчеты в теле письма (используя html и css). Я эту проблему тут озвучила и меня направили сюда.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38030900
seregaLOKI
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Я при помощи данного пакета реализовал отправку таблиц в виде html размером по несколько метров
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38034059
seregaLOKI
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Хотел поинтересоваться есть ли следующая возможность:

Выбираем нужные данные и их отправляем формате xls в качестве аттача с присваиванием ему имени, как я понял у вас реализовано присоединение файлов которые где то у нас хранятся заранее?
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38034766
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
seregaLOKIХотел поинтересоваться есть ли следующая возможность:

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

Да.

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
 -- Из файла 
 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, и второй - просто конвертнуть клоб в блоб.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38044128
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пробую освоить пакет за который автору выражаю огромную благодарность - спасибо!!!. С обычными письмами все работает. Но не могу пока отправить результат запроса (таблица) в аттачменте. Мой код таков:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
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;



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

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

Спасибо за помощь.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38044182
Ura!
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
May12,

Код: plsql
1.
select TABLE_NAME, OWNER, INITIAL_EXTENT INTO blobloc from all_tables where rownum < 21;        


выбираете три поля, а засовываете в одно. да и то как то странно blobloc - это блоб, а вы пытаетесь туда засунуть совсем не блоб
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38044227
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ura!,

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


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

попробовала utl_raw.cast_to_raw, ну и конечно получила по почте прикрепленный ReportResult.htm с набором не понятных символов =(.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38044245
Ura!
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
May12,

Я так понял вам для проверки пихнуть блоб надо? Ну создайте свою табличку с полем BLOB запихните туда что нужно средствами тоада (ну или чем вы там пользуетесь) и считайте это поле в вашу переменную.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38044306
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ura!,
Мне надо отправить письмо с аттачментом в котором будет читаемая таблица. Лягушоноком пользуюсь.

Попробую, таблицу. Единственное я не пойму как из блоба родиться таблица в аттаче. Сообщу по результатам.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38044367
Ura!
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
May12,

:)
Из блоба сама таблица естественно не появится, так же как нельзя таблицу запихать в блоб так как вы пытались. Блоб это тип данных который может содержать чего угодно: исполняемые файлы, картинки, екселевские таблицы, html-ные таблицы и т.д. Оракл не разбирает чего у него там хранится, хранит как есть побайтно. Соответственно что вы туда положите, то он и отправит с письмом (сам пакетом не пользовался, но народ говорит, что оно так и есть)
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38044379
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ura!,
тогда мне остается вариант положить результат селекта в директорию (используя UTL_FILE) и потом его послать с помощью пакета, разработанного автором топика. А если мне в одном письме нужно послать три файла?
Может автор пакета что-то подскажет или если кто решал аналогичную задачу. Спасибо.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38044566
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chameleon82, помоги. =)
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38045408
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
May12Может автор пакета что-то подскажет или если кто решал аналогичную задачу. Спасибо.

В рамках Вашей темы .
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38110284
88888888
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день, может кто подсказать. Нужно отправить HTML-документ как прикрепление, а он постоянно приходит в теле письма в исковерканном виде.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38119140
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ОБНОВИЛ И ВЫЛОЖИЛ ПАКЕТ НА GIT

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

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

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
    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;
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38166932
LimonFX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chameleon82,

на ящики mail.ru и gmail почему-то не отсылает
Тестировал на примере 4) Extension Email with attacments
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38166990
LimonFX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Извиняюсь. Работает всё, просто комп без выхода в интернет был))
Но нашел другую странность, аутлук 2007 и выше почему-то письма с вложением принимает без вложения
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38167929
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Полный пример можете привести?

Проверял на theBat и Outlook, все работало норм, сейчас аутлука под рукой нет.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38168144
LimonFX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В качестве примера использовал 4) Extension Email with attacments
Причем если переслать это же письмо "без вложения" на другой адрес где используется тандерберд, то там вложение присутствует.
Не знаю, может быть тут от настроек аутлука многое зависит
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38239876
Vadim Romanenko
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тоже пользовал пакет. Есть пара вроде бы багов :) Версию взял с GitHub
Отправляю текстовый файл из блоба.
Во-первых, веб-интерфейс Яндекса не видит аттачей. Веб-интерфейс ГМейла - видит, Бат - видит.
Во-вторых, какая-то чехарда с ситуацией, когда тело письма пустое. В этом случае в процедуре не добавляется имя первого файла почему-то :)
Вот этот стремный кусок:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
      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;



Почему ТАК?
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38239924
Vadim Romanenko
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У себя в версии просто убрал прикол с разной отправкой первого файла и всех остальных. Вроде работает :)
Но на Яндексе все равно не показывает аттача... Может как-нибудь покручу в руках аттачи Яндекса...
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38251157
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Vadim Romanenko
Почему ТАК?

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

а вот с яндексом беда. надо будет покрутить )
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38285308
maxdart
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте!

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

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

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

Спасибо за ответы.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38286306
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
maxdartЗдравствуйте!

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

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

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

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

Спасибо. Получение почты в части получения вложений крайне сыро написано (хотя странно, что у вас не видит, у меня на всех тестах иногда показывал больше вложений чем на самом деле из-за недоработанного парсинга, да и проблемы с получением вложений больших обьемов). К сожалению, у самого пока нет времени на дальнейшие доработки, но всегда кто-нибудь может помочь его подправить на GIT ;)
по п.2 пакет надо доработать процедурой типа SET_POPSERVER(p_host, p_port default 110, p_protocol ???); .
а если просто поменять порт на 995 не проходит?
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38293546
krupt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день.
Подскажите, как отправить письмо с картинкой в теле письма, а не как вложение?
Допустим, если в Lotus вставить html-файл с <img src>, то он возьмет файл с диска и запихнет в письмо, но не будет отображать во вложениях.
Спасибо.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38295679
sinitsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
krupt,

в протоколе такой возможности не припоминаю ( гугли на smtp rfc iso ).
отображеним занимается конкретный клиент,
если есть желание, делай заголовки под него.
но другой клиент будет отображать по другому.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38295710
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sinitsaв протоколе такой возможности не припоминаю ( гугли на smtp rfc iso ).да-да, картинки это вотчина протокола smtp.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38295978
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
kruptДобрый день.
Подскажите, как отправить письмо с картинкой в теле письма?


Полагаю, Вы имели ввиду что-то вроде:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
 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;
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38295993
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
kruptДобрый день.
Подскажите, как отправить письмо с картинкой в теле письма, а не как вложение?


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

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
 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

Извиняюсь за пред сообщение, ктрл+ентер случайно нажал, не дописав )
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38296031
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А вообще чтобы правильно вложить изображение, необходимо дописать пакет на наличие идентификатора у вложения,
Код: plsql



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

Код: plsql



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

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

ну а чтобы не отображалось как вложение, допилить чтобы
Код: plsql
1.
Content-Disposition: inline;

или вообще отстуствовало данное свойство
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38296123
krupt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
chameleon82,

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

Добавил поле inline в типе attach_row
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
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, например:
Код: plsql
1.
2.
3.
4.
5.
6.
 PROCEDURE ADD_ATTACHMENT ( dirname IN varchar2
                          , filename IN varchar2
                          , mimetype IN varchar2 DEFAULT 'text/plain'
                          , name IN varchar2 DEFAULT NULL
                          , pinline BOOLEAN := FALSE
                           );



В процедуре Send сделал следующее
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
    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 );

            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;

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



Вроде работает, вот только проблема. Все вложения идут в строке поочереди, как сделать чтобы они были в разных строках?
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38296128
krupt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
chameleon82,

Не видел, что вы уже написали про inline :)
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38296163
krupt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
chameleon82,

Отправку делаю так:
Код: plsql
1.
2.
  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');
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38296260
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
kruptchameleon82,

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

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


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

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

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
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
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38296296
krupt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
chameleon82,

Подскажите на счет
kruptВсе вложения идут в строке поочереди, как сделать чтобы они были в разных строках?
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38297236
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
kruptchameleon82,

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

не совсем понял вопрос.
Для переноса строки в html используется тег <br>
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38297256
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
LimonFXИзвиняюсь. Работает всё, просто комп без выхода в интернет был))
Но нашел другую странность, аутлук 2007 и выше почему-то письма с вложением принимает без вложения

проверил на аутлук 2010, все работает корректно. с последней версией пакета также корректно отображаются и вложения и встроенные изображения.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38365012
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chameleon82, я почитала и поняла, что Ваш пакет может работать с прикрепленными к входящим письмам файлами. Это верное понимание или нужно вчитаться?
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38365603
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
May12,

да, все верно, пример получения вложений во входящей почте описан в комментариях в пакете
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38365758
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добавил примеры с пояснениями на GIT
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38366740
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chameleon82, спасибо, но у меня как всегда не работает.
История стирания ногтей по локти:
восхищаясь тем, что на свете есть такие люди как Вы, я взяла Ваш пакет, откомпилировала и хотела послать письмо себе, процедура отработала, но письма не пришло. Меня насторожили вот эти строчки из Вашего примера:

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



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

Причем пример от Кайта у меня отработал корректно (без вложения, правда). Но предвкушая какие фишечки несет в себе Ваш пакет я бы хотела, чтобы он у меня заработал. вот и пишу к Вам...
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38367031
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
May12,

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


Попробуйте отправить через локалхост, обычно на оракле уже крутится почтовый демон.
Возможно эксчендж проверяет соответствие отправителя, укажите в параметре mailfrom реальный почтовый ящик.
Если не помогло - попросите почтового администратора разобрать логи.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38367189
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chameleon82, сделала с
Код: plsql
1.
MAIL_PKG.SET_AUTH (); 


письмо пришло, потом закоментировала и все работает с локал хостом.
Спасибо и добра Вам.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38370516
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chameleon82, здравствуйте. Пытаюсь забрать почту (посчитать количество писем) с сервера, получаю такую ошибку:
Код: plaintext
1.
2.
3.
4.
5.
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; расскоментирован, но подробнее описание ошибки не вижу.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38370561
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
May12chameleon82, здравствуйте. Пытаюсь забрать почту (посчитать количество писем) с сервера, получаю такую ошибку:
Код: plaintext
1.
2.
3.
4.
5.
Error at line 1
ORA-29260: ошибка сети: не соединен
ORA-06512: на  "MAYA.MAIL_PKG", line 522
ORA-06512: на  line 28
ORA-29260: ошибка сети: TNS:нет прослушивателя 


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


May12MAIL_PKG.DEBUG := TRUE; расскоментирован, но подробнее описание ошибки не вижу.
DBMS_OUTPUT включите и смотрите его, там весь процесс общения с сервером, но ввиду ошибки выше общение еще даже не начиналось
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38370623
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chameleon82Какая версия оракла?
10.2. указывать разрешение по доступу это как тут написано?


chameleon82DBMS_OUTPUT включите
Ясно.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38370668
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
May12,

не, там про 11 написано. сорри.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38370759
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Видимо, мне не забрать почту. =(
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38370770
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
May12Видимо, мне не забрать почту. =(возможно данный пакет умеет забирать почту только через попу, а на эксчендже доступ к ней не проходит через порты.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38371014
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
-2-,
авторвозможно данный пакет умеет забирать почту только через попу,

да, через pop3. А на эксчендже IMAP и надо админов просить что-то сделать чтобы почту забирать через pop3.
что же делать...
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38371772
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
May12-2-,
авторвозможно данный пакет умеет забирать почту только через попу,

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

Да, до IMAP еще руки не дошли, только с POP3 пока работает
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38371775
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
May12что же делать...
Настройте пересылку на ящик, к которому есть доступ по pop
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38372464
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chameleon82, по телнету 110 порт открывается. выполняю код:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
 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 лога общения с сервером не выводит. уже близко. помогите, молю.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38372660
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
May12процедура отрабатывает, но количества писем не возвращает, в dbms_output лога общения с сервером не выводит. уже близко. помогите, молю.
Забыл уточнить:
Код: plsql
1.
  MAIL_PKG.DEBUG_LEVEL := MAIL_PKG.DEBUG_ALL;


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


надо:
Код: plsql
1.
  MAIL_PKG.SET_AUTH ('maya','pass');
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38372813
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chameleon82, уже совсем близко =)), но пока результат таков:

Код: plaintext
1.
2.
+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.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38372824
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
может проблема в ssl?
Код: plaintext
For exchange 2010, by default, the server would need the client use ssl for pop3.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38373062
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
May12может проблема в ssl?
Код: plaintext
For exchange 2010, by default, the server would need the client use ssl for pop3.


Возможно. Обновил немного пакет, попробуйте еще раз с новой версией вывести лог
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38373096
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chameleon82, заработало. Ошибка в моем случае была в домене и доступности порта.

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

chameleon82, спасибо и добра Вам.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38373433
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
May12Также важно чтобы SSL шифрование по этому порту отсутствовалоSSL-шифрования на 110 порту не может быть по определению. Или STARTTLS или 995-й порт.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38373718
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. Sidorov,
да, не может. не поспоришь.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38418602
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ребят, не подскажите с чем связано странное поведение пакета =)) или не пакета.

Если отправлять письмо с вложением, то оно не отправляется, не приходит на почту. Если закомментировать функцию MAIL_PKG.ADD_ATTACHMENT и снова выполнить, то приходит письмо с аттачментами!!! В письме столько аттачментов сколько раз была выполнена ранее процедура с незакомментированной MAIL_PKG.ADD_ATTACHMENT. Т.е. складывается впечатление, что в письмо набиваются файлы и потом отправляются.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38418613
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А воооот и ошибка:
Код: plaintext
1.
2.
ORA-06502: PL/SQL: : буфер символьных строк слишком маленький ошибка числа или значения
ORA-06512: на  "MAYA.MAIL_PKG", line 163
ORA-06512: на  line 9
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38418649
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
но как её пофиксить не пойму =(( вот на этой строке пакета:
Код: plsql
1.
LAST_ATTACHMENT_ID := GENERATE_CONTENT_ID(MAIL_PKG.attachments.count);



chameleon82, need your help!
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38418849
Фотография maddistortion
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
May12,

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


возвращает значение большей длины чем
Код: plsql
1.
LAST_ATTACHMENT_ID VARCHAR2(25) := NULL;
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38419028
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maddistortion, спасибо за отклик.
Увеличила до 500
Код: plsql
1.
 LAST_ATTACHMENT_ID VARCHAR2(500) := NULL;


ошибка:
Код: plaintext
1.
2.
ORA-06502: PL/SQL: : буфер символьных строк слишком маленький ошибка числа или значения
ORA-06512: на  "MAYA.MAIL_PKG", line 164
ORA-06512: на  line 11
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38419055
Фотография maddistortion
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
May12,
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
 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 тоже попробуйте увеличить
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38419075
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maddistortion,

Вы - чудо. Добра Вам.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38429275
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я извиняюсь, вопрос уже поднимался, в том числе мной, но в других ветках и безрезультатно.
Сейчас хочу отправить таблицу в теле письма с помощью замечательного пакета mail_pkg. Наставьте на путь истинный? Что делать?

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

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
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;
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38429318
andreiz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chameleon82,
интересно, у меня другая задача - читать письма с exchange 7, сохранять тело как "чистый" текст в CLOB, ну и как BLOB, сохрранять все аттачки как BLOB. делаю на яве в банке, больше всего трудностей с коонвертированием тела в "чистый" текст. у кого есть опыт поделитесь.
заранее спасибо.
всего.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38429338
andreymx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
May12
Код: plsql
1.
2.
3.
4.
5.
6.
EXCEPTION
   WHEN NO_DATA_FOUND THEN
      NULL;
   WHEN OTHERS THEN
      NULL;
END;

интересно, как ты поймёшь, где и когда произошла ошибка?
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38429390
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andreiz, если я правильно поняла смотрите тут https://forums.oracle.com/thread/2398323
там создаются две таблички, java-класс в базе и обертка , в результате из ящика данные загружаются в две таблицы - боди и атачменты.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38429401
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andreymx, упс, забыла удалить. но мне кажется я концептуально что-то не то делаю. в принципе не пойму как таблицу засунуть в тело письма.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38429529
andreiz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
May12,
да всё примерно так, одна беда
"// -- Body is also multipart (both plain text and html)."
начиная с "exchange server 2007" он не шлёт больше "multipart и даже plain text" только html плюс всякие там encoding...
а так очень похоже
спасибо
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38429553
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chameleon82, без Вас не справлюсь. Помогите отправить таблицу
Код: plsql
1.
2.
3.
4.
5.
 select '<TD>'||'Помоги'||'</TD>' ||
          '<TD>'||'тупой'||'</TD>'||
          '<TD>'||'учиться!!!'||' </TD>'||
           chr(10)  as STR
      FROM DUAL CONNECT BY LEVEL < 5;



в теле письма? Молю...
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38429672
andreiz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
May12,

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


select '<TD>'||'Помогу'||'</TD>' ||
... FROM DUAL CONNECT BY LEVEL < 5;
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38429686
andreiz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
сайт не пропустил, пробую ещё раз
'<' на '&'||'lt;' и '>'на '&'||'gt;'

select '&'||'lt;'||'Помогу'||'&'||'gt;'||
... FROM DUAL CONNECT BY LEVEL < 5;
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38429860
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andreiz, =((
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38429926
K790
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
May12,

mb
Код: plsql
1.
2.
3.
4.
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;
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38429935
K790
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
May12,

sry

Код: plsql
1.
2.
3.
4.
5.
6.
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;
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38429998
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
K790, спасибо. Так и делаю. Читаю отсюда . вот только кинуть на почту это хочется все-таки с использование mail_pkg.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38431571
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
May12, кидай в свое удовольствие через:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
 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
                  );



=))
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38432291
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
May12chameleon82, без Вас не справлюсь. Помогите отправить таблицу
Код: plsql
1.
2.
3.
4.
5.
 select '<TD>'||'Помоги'||'</TD>' ||
          '<TD>'||'тупой'||'</TD>'||
          '<TD>'||'учиться!!!'||' </TD>'||
           chr(10)  as STR
      FROM DUAL CONNECT BY LEVEL < 5;



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

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

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
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;          
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38432305
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Кстати, Ваш запрос в PLSQL в Oracle9i выдаст одну строку вместо 4-ех, в версиях старше будет все норм. Это известная бага 9-го оракла при выборе произвольных данных из таблички DUAL. Будьте внимательны
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38432315
Вячеслав Любомудров
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Это бага не оракла, а инструмента
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38432318
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
andreizchameleon82,
интересно, у меня другая задача - читать письма с exchange 7, сохранять тело как "чистый" текст в CLOB, ну и как BLOB, сохрранять все аттачки как BLOB. делаю на яве в банке, больше всего трудностей с коонвертированием тела в "чистый" текст. у кого есть опыт поделитесь.
заранее спасибо.
всего.

Пока пакет может только с некоторыми ограничениями забирать почту с pop3, сейчас как раз работаю над получением почты через протоколы IMAP и MAPI (с последним работает exchange).
С конвертированием тела в текст в данном пакете особых проблем не наблюдалось, по крайней мере, с английским текстом проблем точно нет. Русский текст в моих тестах вполне декодируется, но я тестировал не на всех кодировках. Для приема почты с помощью mail_pkg попробуйте пересылать почту на pop3 ящик.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38439342
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), не помогло
все равно вылетает там же.

что делать?
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38439352
mr Red
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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)
помогло
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38459981
oleggy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Всем привет.
Вопрос скорее всего к chameleon82 или может быть кто то другой знает.
Данный скрипт отправки почты возможно выполнить в SQL Plus ?
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38461452
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
oleggy, это мой пятый совет в форуме (пытаюсь немного помочь -2-): вам нужно скомпилировать предложенный пакет и выполнять из него процедуры. инструмент (sql plus или что-то другое) не имеет значения. Однако с таким объемом кода, на мой взгляд, удобнее работать в Toad или pl/sql developer.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38461511
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Друзья, подскажите пожалуйста как отправить почту на внешний домен? приходит вот такая "отбивка":

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Не удалось выполнить доставку следующим получателям или группам:
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#

т.е. понятно что отправка, видимо, запрещена. Каким способом сделать отправку возможной?
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38461787
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
May12Друзья, подскажите пожалуйста как отправить почту на внешний домен? приходит вот такая "отбивка":

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

Ну это Вам к администратору почтового сервера, сложно сказать, какие фильтры у него настроены. Попробуйте в адресе почты отправителя указать правильный почтовый домен (или существующую учетную запись).
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38461977
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chameleon82Попробуйте в адресе почты отправителя указать правильный почтовый домен (или существующую учетную запись).
да, так и сделала и получила "отбивку". =)
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38462168
PooH_2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну вам же пишут "Допустимые адреса выглядят следующим образом: username@contoso.com"
Это настройка вашего почтового сервера, он другую почту слать не хочет. Надо это ограничение изменить или отключить. Но к ораклу это уже не имеет никакого отношения.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38489215
Фотография l_kator
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chameleon82,
спасибо вам огромное!! Вы спасли мой мозг :)

У меня всего 2 вопроса:
Как подписаться на рассылку обновленной версии пакета?
Куда слать пиво(цветы/вино/шоколад/котлеты)?
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38510871
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chameleon82, с наступающим и добра Вам.

Повторно наткнулась на проблему ограничения длины, в в этот раз, названия файла. Чтоб люди еще меньше мучились предлагаю заменить type attach_row на:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
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'
                           );
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38510927
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
May12,

перекомпилируй с nls_length_semantic=char. и имей ввиду, что большинство файловых систем не поддерживают имена более 25 5 символов.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38516395
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
l_kator chameleon82,
спасибо вам огромное!! Вы спасли мой мозг :)

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

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

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

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

И всем тоже счастливого Нового года! )
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38534223
Vadim Romanenko
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Привет всем!

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

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

С уважением, Вадим.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38534227
Vadim Romanenko
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ПС: присоединяюсь к поздравлениям с Новым годом. Путь и поздновато, конечно :)
Желаю всем побольше творческих решений, и поменьше ковыряния в старом, особенно чужом ;)
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38544489
AntonG
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Доработал процедуру получения почты, теперь не падает и не виснет при больших входящих письмах
GET_MAIL
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
 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;


...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38551518
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Возможен оффтоп.
Кто-нибудь пытался вставить, скажем, график роста своей зарплаты в рассылаемые письма?
какой процедурой (или на java) создать график, как его сохранить и вставить в письмо (вставка более менее понятна =) )?
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38551595
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
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
;
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38551895
Asmodeus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
-2-, замечательно!
З.Ы. Какое, однако, забавное "пи" используется. :-)
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38551936
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AsmodeusЗ.Ы. Какое, однако, забавное "пи" используется. :-)Со школы уже столько "пи" прошло..., что девятка из памяти выпала.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38551941
Фотография orawish
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
-2-AsmodeusЗ.Ы. Какое, однако, забавное "пи" используется. :-)Со школы уже столько "пи" прошло..., что девятка из памяти выпала.
acos(-1) надёжнее
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38562843
LordOfOrder
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chameleon82, во-первых, спасибо Вам большое за этот пакет. Очень сильно помог в работе и сэкономил уйму времени!
Во-вторых, хочу сообщить о проблемах:
1) Отправляем на почту вложением файл xlxs. Я получал такое письмо на yandex-е, и получалось так, что ContentTransferEncoding принимал значение null, поэтому на диск сохранялась всякая херня.
Я не стал особо копаться и заморачиваться и тупо прописал это в коде:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
 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:
Код: plsql
1.
2.
3.
CONVERT(UTL_RAW.cast_to_varchar2(UTL_ENCODE.base64_decode(UTL_RAW.cast_to_raw(
'CgrQodGD0LHRgdC40LTQuNC4INCx0Y7QtNC20LXRgtC90YvQvCDRg9GH0YDQtdC20LTQtdC90LjR'
))), 'CL8MSWIN1251', 'UTF8')


, то происходит ошибка. Потому что идет разрыв в символах. Если убрать в конце 'R' или добавить 'j9' из начала новой строки, то все пройдет хорошо. Сам метод конвертации по-частям ущербен. Нужно сначала собирать все в одну кучу, а потом одной операцией конвертить.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38563033
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
LordOfOrderchameleon82, во-первых, спасибо Вам большое за этот пакет. Очень сильно помог в работе и сэкономил уйму времени!

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

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

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

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

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

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

ПыСы: чтение почты пакетом все еще пока в экспериментальном состоянии :)
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38563840
LordOfOrder
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
1) По первой ошибке - см. Приложение. Я еще раз проверил - да, без моей вставки не работает.
2) Еще одна проблема - на некоторых письмах может возникать ошибка в блоке:
Код: plsql
1.
2.
3.
4.
5.
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>" оно и крашится.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38563842
LordOfOrder
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если это поможет, то по 2 ошибке письмо:
1) Пересылаемое
2) Приходит на почту на сервисе https://vhost5.sibdc.ru/webmail

Кхм...неужто выходит так, что по строчкам вообще не стоит делать разбор? Или "=" - это знак переноса строки? Тогда Вам придется запилить обработку переноса?
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38563843
AntonG
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день,
я тоже заинтересован в процессе получения почты, поэтому вот моя исправленная/дополненная версия

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

1. исправлена проблема построчной конвертации
2. добавлена возможность перезаписывать вложения когда в одном почтовом сообщении содержится несколько частей, содержащих одну и ту же информацию например в text/plain и text/html
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38566964
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Vadim RomanenkoПривет всем!

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


sys.obj$.name (который Вы видите через all_directories) = varchar2(30) ни больше, ни меньше. Это алиас, а не полный путь, обратите на это внимание
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38686082
Bios852
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
chameleon82,

Помогите. Скопировал пакет, скомпилировал нормально. При попытке отправить письмо все время ругается на utl_smtp.Mail(v_Mail_Conn, sndr.rcptmail); в процедуре send, пишет Syntax error. Почему? Версия Oracle 8 или 9 точно не помню сейчас нет возможности посмотреть.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38690329
jan2ary
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тут Javamail API упоминался, на всякий случай оставлю это здесь
Код: plaintext
Sending Mails Through Java Stored Procedure Fails After Database Upgrade to 11.2.0.4 (Doc ID 1631194.1)
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38703815
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Bios852,

пакет работает на версии оракла 9 и выше
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38709198
igor_gar
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
При использовании пакета с отправкой почты без атача, при вызове пакета возвращает ошибку: ORA-06531: Reference to uninitialized collection . Версия Oracle 11.2.0.4.

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



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

Код: plsql
1.
2.
type attach_list is table of attach_row;
 attachments attach_list := attach_list();
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38759815
Egoza
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день!
У меня 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 ?
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38761671
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Egoza, подбиралось экспериментальным путем. Стоит помнить, что длина строки письма не должна превышать 76 символов, в противном случае почтовые клиенты могут неправильно обрабатывать полученный текст
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38761894
Egoza
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
chameleon82, спасибо за пояснение.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38764156
Snezhanka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
почему именно 76 символов? не помню про это ограничение
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38764158
Вячеслав Любомудров
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Snezhankaпочему именно 76 символов? не помню про это ограничениеЭто не совсем ограничение
Скорее правило хорошего тона
http://tools.ietf.org/html/rfc2822#section-2.3
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38764192
AG#
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38764193
AG#
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AG#,

No special semantics are attached to these tokens. They are simply
single characters.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #38815045
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Исправлена ошибка с получателями, стоявшими в копии письма, спасибо пользователю llocust Git
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39053829
Фотография May12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ребят, а у вас на группы рассылки нормально письма ходят? у меня ошибка:
Код: plaintext
 ORA-29279: Постоянная ошибка SMTP: 550 5.1.1 User unknown
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39054606
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
May12, проверьте пользователей в рассылке, такая ошибка возникает, когда ящика одного из пользователей в рассылке не существует.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39171415
6eper
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
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

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

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

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

Благодарен за ответ.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39179281
bounce message
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ljucius11и я лучше промолчупоздно метаться, уже сказал.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39179455
Ljucius11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
bounce messageLjucius11и я лучше промолчупоздно метаться, уже сказал.

Того требует заказчик
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39183272
Ljucius11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ljucius11bounce messageпропущено...
поздно метаться, уже сказал.

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

Тем более что он не умеет настраивать почтовый сервер, приходится делать кастыли
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39192246
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
6eper,

Добрый день. Пока не реализовал (
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39246126
fadeevpv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
chameleon82,

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

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

спасибо !
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39247805
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
fadeevpv,
День добрый. Пакет устанавливается и работает независимо. Так что забирайте целиком :)
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39247838
blkangel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
chameleon82fadeevpv,
День добрый. Пакет устанавливается и работает независимо. Так что забирайте целиком :)

Ну как же независимо. Зависит от UTL_SMTP, UTL_TCP. на которые надо дать разрешения. :)
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39294001
ikonst
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Может быть кому-то пригодиться, ну и мне чтобы не забыть.

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

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

Настройка stunnel зависит от ОС и требует некоторых действий.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39327278
A_Karetnikov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Всем доброго дня!
Сломал себе голову, мне необходимо отправлять результат запроса на соответствующий email с помощью процедуры в pl/sql
Процедура ниже
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
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
Помогите пожалуйста.
Всем спасибо!
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39327406
andreymx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
A_Karetnikov

А оракл тут при чём?
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39328003
A_Karetnikov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Мне кажется проблема в этом параметре p_attach_mime VARCHAR2(200) := 'application/octet-stream';
Если его правильно подобрать, то можно решить проблему, описанную в пункте 1
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39328172
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
A_KaretnikovМне кажется ты преувеличиваешь роль mime_type для твоей ситуации. И в любом случае оракл тут не причем.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39328329
A_Karetnikov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Можно ли формировать файл с расширением xlsx?
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39330686
A_Karetnikov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Помогите пожалуйста, возможно текст процедуры написан неверно
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39330767
Фотография Fogel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
A_KaretnikovМожно ли формировать файл с расширением xlsx?
можно
попроси "больших людей" купить вот это
или сам разберись в xml структуре формата xlsx (а у него именно xml структура) и как оракловые данные заворачивать в xml
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39330794
Фотография orawish
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
A_KaretnikovПомогите пожалуйста, возможно текст процедуры написан неверно
для начала - вас не смущает незакрытый апостроф в первой строке?
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39330841
A_Karetnikov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
orawish,

Текст процедуры я правил в рамках сокрытия конфиденциальных данных. На бою у меня все это есть
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39330854
A_Karetnikov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
При этом, если я сохраню сформированный файл на компьютере, а затем его снова открою и нажму "сохранить как", то предлагает сохранить тип файла как "Текстовые файлы (с разделителями табуляции) (*.txt)"
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39330859
dba123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
A_Karetnikov,

замени '.xls' на '.csv'
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39331229
A_Karetnikov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
dba123,

Если я так сделаю у меня все столбцы склеются в один.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39331243
A_Karetnikovdba123,

Если я так сделаю у меня все столбцы склеются в один.выложи сюда файл, который получился в результате у получателя
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39331584
A_Karetnikov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Решено.
Если вначале файла csv добавить "sep=,"
То происходит разделение на столбцы
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39398896
andreymx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
как запросить уведомление о прочтении?
Я сам этого не люблю, но клиент запросил

в CDO+c# как-то так:
Код: c#
1.
oMsg.DSNOptions = CDO.CdoDSNOptions.cdoDSNSuccess; //для получения уведомления о доставке и прочтении



в CDO+EWS как-то так:
Код: c#
1.
mail.IsReadReceiptRequested = is_readReceipt;




Как протолкнуть через в utl_http?
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39398917
andreymx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andreymxкак запросить уведомление о прочтении?
Я сам этого не люблю, но клиент запросил

в CDO+c# как-то так:
Код: c#
1.
oMsg.DSNOptions = CDO.CdoDSNOptions.cdoDSNSuccess; //для получения уведомления о доставке и прочтении




в CDO+EWS как-то так:
Код: c#
1.
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]
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39398918
andreymx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вроде такое чего-то накропал, и даже работает
Код: plsql
1.
2.
3.
4.
5.
    IF Confirm_Reading = '1' THEN
    
       utl_smtp.write_data(v_Mail_Conn, 'Disposition-Notification-To: ' || '4' || crlf );
       
    END IF;
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39404676
trace.log
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вопрос знактокам:
Как на выходе получить файл с нижним подчеркиванием??
Вот кусок кода:
Код: sql
1.
'REPORT_' || TO_CHAR (date_to + 1, 'rrrrmmdd') || '.html',


Но на почту приходит файл без '_', почему? куда смотреть?
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39404716
trace.log
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Уже все возможное пересмотрел и все равно приходит в почте файл: REPORT 20170215.html
Неужели почтовик съедает этот символ?
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39497860
PsyDiamond
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
вопрос к знатокам (хотя может ответ всё же лежит на поверхности)

вот есть отправка blob в качестве вложения. отчего зависит время прикрепления блоба?

а-ля

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
/* Содержимое файла */
		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.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39543083
Дмитрий_86
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
trace.logВопрос знактокам:
Как на выходе получить файл с нижним подчеркиванием??
Вот кусок кода:
Код: sql
1.
'REPORT_' || TO_CHAR (date_to + 1, 'rrrrmmdd') || '.html',


Но на почту приходит файл без '_', почему? куда смотреть?


Аналогичная проблема, не знаю что делать, а край надо.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39543160
Дмитрий_86
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Дмитрий_86trace.logВопрос знактокам:
Как на выходе получить файл с нижним подчеркиванием??
Вот кусок кода:
Код: sql
1.
'REPORT_' || TO_CHAR (date_to + 1, 'rrrrmmdd') || '.html',


Но на почту приходит файл без '_', почему? куда смотреть?


Аналогичная проблема, не знаю что делать, а край надо.

Сделал небольшой костыль:

Проблема возникает в результате шифрования функцией ENCODE, почему то она заменяет все символы '_' на ' ', решил не заморачиваться, сделал условие по теме письма, в котором наличие '_' критично,
вместо
utl_smtp.write_data(v_Mail_Conn, ' filename="' || MAIL_PKG.ENCODE(MAIL_PKG.attachments(x).name) || '"' || crlf);

запилил

if substr(MAIL_PKG.attachments(x).name, 1, 4) = 'KO_P' then
utl_smtp.write_data(v_Mail_Conn, ' filename="' || MAIL_PKG.attachments(x).name || '"' || crlf);
else
utl_smtp.write_data(v_Mail_Conn, ' filename="' || MAIL_PKG.ENCODE(MAIL_PKG.attachments(x).name) || '"' || crlf);
end if;

Естественно в названии файла не должно быть русских символом, иначе трюк не сработает.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39578606
andreymx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
на всякий случай - в пакете не прописано закрытие соединения

поэтому работа чревата ошибкой ora-30678
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39578613
andreymx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andreymxна всякий случай - в пакете не прописано закрытие соединения

поэтому работа чревата ошибкой ora-30678сорри, поторопился, там quit стоит
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39605010
Lemkoleg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый день. Можете выложить окончательный вариант пакета? Спасибо
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #39615714
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
Передача письма с вложением. Готовое решение
    #39943447
dmdmdm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
declare
  v_message varchar2(10000) := '';
  v_subject varchar2(100) := 'mail test';
  v_recipient varchar2(100) := 'maslov.d@sandy.ru';
begin
    v_message := v_message || '<style>table, th, td {  border: 1px solid black;  border-collapse: collapse; } </style>
    <TABLE><TR><TD>Артикул<TD>Название<TD>Цена</TR>';
    
    for c in (select lpad(rownum, 6, '0') article, 'Товар '||rownum name, round(dbms_random.value()*1000, 0) itemprice from dual connect by level < 6) loop
      v_message := v_message ||'<TR><TD>'||c.article||'<TD>'||c.name||'<TD>'||c.itemprice||'</TR>';
    end loop;
    v_message := v_message || '</TABLE>';
    
    MAIL_PKG.SEND(mailto   => v_recipient,
                  subject  => v_subject,
                  message  => v_message,
                  mailfrom => NULL,
                  mimetype => 'text/html',
                  priority => NULL,
                  cc       => NULL);
end;



ORA-29279: SMTP permanent error: 504 5.7.4 Unrecognized authentication type
ORA-06512: at "SUPERMAG.MAIL_PKG", line 460
ORA-06512: at line 14

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
    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;



Верно ли понимаю, что данный сервер настроен не принимать юзера/пароль в plain text ?
Код: powershell
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
220 srv-exch-01.noht.local Microsoft ESMTP MAIL Service ready at Fri, 3 Apr 2020 12:04:32 +0300
EHLO maslovd
250-srv-exch-01.noht.local Hello [192.168.1.200]
250-SIZE
250-PIPELINING
250-DSN
250-ENHANCEDSTATUSCODES
250-STARTTLS
250-X-ANONYMOUSTLS
250-AUTH NTLM
250-X-EXPS GSSAPI NTLM
250-8BITMIME
250-BINARYMIME
250-CHUNKING
250-XEXCH50
250-XRDST
250 XSHADOW
QUIT
221 2.0.0 Service closing transmission channel
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #40011826
andreymx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
longman
отвечаю сам себе) чтоб подобных лишних вещиц не было, надо в поле Content-Type при формировании письма, а точнее секции вложений необходимо указать не стандартный text/plain ( text/html ), а что-то типа APPLICATION/MSWORD для doc -ов, APPLICATION/PDF для pdf -ов.. вот как бы и всё решение.. также реализовал использование HTML -файла вместо текстового body письма (понятно, что можно просто в body передать теги, но конечный пользователь такими знаниями увы не владеет).. в целом ничего сложного, кому нужно спрашивайте.. всем спасибо..
коллеги
а как бы в плскл получить весь список для конвертации типов файлов в Content-Type?
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #40011834
andreymx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andreymx
longman
отвечаю сам себе) чтоб подобных лишних вещиц не было, надо в поле Content-Type при формировании письма, а точнее секции вложений необходимо указать не стандартный text/plain ( text/html ), а что-то типа APPLICATION/MSWORD для doc -ов, APPLICATION/PDF для pdf -ов.. вот как бы и всё решение.. также реализовал использование HTML -файла вместо текстового body письма (понятно, что можно просто в body передать теги, но конечный пользователь такими знаниями увы не владеет).. в целом ничего сложного, кому нужно спрашивайте.. всем спасибо..
коллеги
а как бы в плскл получить весь список для конвертации типов файлов в Content-Type?
в VS скачал нагетом пакет MimeMapping.
как вариант - достать оттуда нужные типы и вбить в справочник или руками

или есть более корректный вариант?
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #40011838
проходил мимо...
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #40011842
andreymx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
спасибо
но что-то я там *.xlsx не могу найти...
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #40011872
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
applcation/x-ms-office
?
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #40011881
andreymx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. Sidorov
Код: plaintext
applcation/x-ms-office
?
не понимаю

как сопоставить applcation/x-ms-office и xlsx
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #40011884
Фотография env
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andreymx,

Как вариант - отправить себе письмо с аналогичным файлом и посмотреть служебные заголовки.

Или application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #40011886
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andreymxили есть более корректный вариант?

В Windows это сопоставление прописано в реестре и может изменяться по желанию. У Апача для
этого специальный модуль с конфигом.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #40011889
andreymx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov
andreymxили есть более корректный вариант?

В Windows это сопоставление прописано в реестре и может изменяться по желанию. У Апача для
этого специальный модуль с конфигом.отправляли вложения zip'ы 10 лет с content-type = plain/text
и всех всё устраивало
вдруг нашелся какой-то получатель, который требует application/zip
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #40011900
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andreymxотправляли вложения zip'ы 10 лет с content-type = plain/text
и всех всё устраивало

Значит у вас хреново с саппортом и мат получателей битых архивов до вас не доходил. Это
как у одной известной фирмы: "Error sending error report: Error 404".

[HKEY_CLASSES_ROOT\.zip]
@="CompressedFolder"
"DontCompressInPackage"=""
"PerceivedType"="compressed"
"Content Type"="application/x-zip-compressed"
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #40011908
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Нет желания "особо думать" - выставляете application/octet-stream для всего, кроме узкого круга текстовых файлов.
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #40011945
andreymx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. Sidorov
Нет желания "особо думать" - выставляете application/octet-stream для всего, кроме узкого круга текстовых файлов.
сделал справочник
основные типы закачал - txt csv doc docx xls zip rar pdf и т.д.
для ненайденных сделал application/octet-stream
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #40044684
Shtok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Товарищи, помогите, куда смотреть.
Есть пакет рассылки писем с вложениями - прекрасно работает на любые "ящики", кроме писем на GMAIL. На gmail приходит письмо:

Код: html
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
--BB1511AFEE820D04E0535128280AE49C
Content-Type: text/plain;
 charset=windows-1251

Grafic

--BB1511AFEE820D04E0535128280AE49C
Content-Type: application/octet-stream; name="grafik.xlsx"
Content-Disposition: attachment;
 filename="grafik.xlsx"

Content-Transfer-Encoding: base64

UEsDBBQABgAIAAAAIQC+pOOLlQEAAC4GAAATAAgCW0NvbnRlbnRfVHlwZXNdLnht
bCCiBAIooAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
....


При этом, если скачать письмо с gmail и открыть в outlook - открывается и все корректно отображает, в том числе и вложение (вложения не битые)
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #40131430
andreymx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
через облачный exchange (EWS) кто-то пробовал оправлять-получать почту?
...
Рейтинг: 0 / 0
Передача письма с вложением. Готовое решение
    #40131616
andreymx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andreymx
через облачный exchange (EWS) кто-то пробовал оправлять-получать почту?
админы пятый год грозятся smtp отключить
...
Рейтинг: 0 / 0
274 сообщений из 274, показаны все 11 страниц
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Передача письма с вложением. Готовое решение
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]