Extract part of an email with Automator
I would like to try and start using automator for a task and wondered if this if possible.
search through my email messages find all iTunes receipts
get the date and the total and copy to excel spreedsheet in the following format
15/12/2014 5.97
then move the message to a receipts claimed folder and find the next one
Here's what you could do.
First make sure you have both images open in editor
1. Open the image and select the area using the magnetic lasso/quick selection tool.
2. Select Layer -> New -> Layer Via Copy
3. Now in the layers palette, right click the layer and select 'Dulicate Layer'
4. In the duplicate layer dialog, in document - select the other image, where you would like to paste the image to.
5. You and ajust the poition of the pasted area/resize it using the move tool or transform tool (Ctrl + T).
6. Save the image with a new name
If you simply want to save the image with transparency (after step #2) - you may -
> hide the previous layer and Save the image as a png/gif so transparency is presereved.
Hope that helps.
When you have teh saved documents you can open them up in different editors.
Regards,
Similar Messages
-
Extract part of image & save with transparent background
What is the best way to extract part of an image & save it with a transparent background? I had hoped to the extracted images in 2 different ways.
Firstly just to paste into another image.
Secondly I'd like to try to open both the extracted item as well as the whole original photo in different video editing programs including Premiere Elements & sony Vegas. What is the best way to do this?Here's what you could do.
First make sure you have both images open in editor
1. Open the image and select the area using the magnetic lasso/quick selection tool.
2. Select Layer -> New -> Layer Via Copy
3. Now in the layers palette, right click the layer and select 'Dulicate Layer'
4. In the duplicate layer dialog, in document - select the other image, where you would like to paste the image to.
5. You and ajust the poition of the pasted area/resize it using the move tool or transform tool (Ctrl + T).
6. Save the image with a new name
If you simply want to save the image with transparency (after step #2) - you may -
> hide the previous layer and Save the image as a png/gif so transparency is presereved.
Hope that helps.
When you have teh saved documents you can open them up in different editors.
Regards, -
Sending an HTML email with Automator
I am trying to send a HTML postcard that I created to a list of 200 friends for a golf tournament. I would like to use Automator to send the emails to each user individually and not to the entire group at once.
So far I found one Automator action that will create an email message from a Safari page but my trouble is entering the addresses from my address book group for all 200 emails.
Could someone help me with a workflow?
Thanks in advance,
AdamTry this
<%@ page import="sun.net.smtp.SmtpClient,java.io.PrintStream" %>
<%
try{
String host = "IP"; //this is u r IP adress
String from = "[email protected]"; //mail adress of sender
String to = "[email protected]"; //mail address whom to
SmtpClient smtp = new SmtpClient(host);
smtp.from(from);
smtp.to(to);
PrintStream out1 = smtp.startMessage();
out1.println("To: " + to);
out1.println("Subject: Hello peter ");
out1.println();
out1.println("Hi Peter How r u doing ");
out1.flush();
out1.close();
smtp.closeServer();
catch(Exception e)
out.println(e+e.getMessage());
%> -
Hi
I want to send one email to 400 people once a month. Is their a workflow in automator that can help. I kniw their are account limits so if I could stagger the sending that would be good. Also they need to be BCC as confidentiality is important.
Automator doesnt seem to want to cooperate any ideas for a workflow ?
thanks in advanceFirst, use an action to get the file-since you want this to go automatically
1. Get Specified Finder Items (on the outgoing folder)
2. Get Folder Contents
Then add that file to the message:
3. New Mail Message
4. Send Outgoing Messages
Notes:
1-The first action should point to the folder containing the file to be sent out and the file(s) to be sent should be the only thing in the folder. This is so that the workflow will go automatically without you having to select the file or change the workflow everytime.
3-Fill in the To: with your email address and the Bcc: with one of the groups. You will need to save and schedule a copy of the workflow for each group.
If you were going to send out a different file every week to the same groups of people, you could schedule another workflow to replace the previous week's file with the new week's. You will have an outgoing folder and a working folder. Use a workflow to copy from the working folder to the outgoing folder.
Get Specified Finder Items (on the outgoing folder)
Get Folder Contents
Move Finder Items (if you wanted to an archive folder or the Trash)
Get Specified Finder Items (on the working folder) - click Files/Folders and Ignore Results to create a break in the workflow
Get Folder Contents
Copy Finder Items (to the outgoing folder)
Schedule this workflow to run once a week or month as needed but before any of the current week/month's cycle of group emails. It could even be run as a folder action if you wanted the new file to be set up as soon as you saved it to the working folder. -
Extracting part of a string with a delimiter
Hi. Is there a function that can take the string below, and extract EITHER everything to the left OR the right of the " | " separator? I have many string fields with the same format and need to split them apart. They all contain the same separator but I haven't come across anything that works.
Thanks.
"Communication | 6. Invites feedback, discussion and/or suggestions about his/her own ideas and assumptions"Hi,
You can use the Split function. This will convert your string to an array with a defined seperator like:
StringVar myString;
myString := "Communication | 6. Invites feedback, discussion and/or suggestions about his/her own ideas and assumptions"
Split (myString, "|") [1];
This will retrieve the first element in the array which is "Communication ".
Good luck,
Brian -
When I receive an email with and HTML included I get the following message: "There are no parts that can be displayed inline", but no document to open.
== This happened ==
Every time Firefox opened
== a month agoI don't know. I don't have access to Iquest, and some searching on google for ''Iquest webmail "There are no parts that can be displayed inline"'' doesn't really turn up anything.
Does Iquest have their own support? -
I put together and sent 10 pictures from my granddaughter's birthday party. Is there a way of sending them with a link recipients can click on, rather than having all the pictures download as part of the email message?
Hello userlarry, do you have Mobile Me? You could use that. Or you could compress them, you would still need to send them in an email, but it would help with size limitations of emails.
To compress them, put them in a folder and right click on the folder. You should see a Compress option. Then just drag the .zip file into your mail.
Regards,
Graham -
Automator Service to Upload to FTP and Send Email With Links
Hello.
Since updating my client server machines at work to 10.7, the automator workflow that I have been using for years isn't working correctly. Basically it's a simple workflow that uses upload to FTP action version 1.5 that uploads a video file to an FTp server, copies the links to the clipboard, creates new mail message and sends it.
For some reason, it only does 1 file at a time now. Interestingly, it uploads the files to the server but only sends the email with the first link this worked perfectly fine on 10.6 Before you could highlight 10 files and it would upload and send the links to all of them.
Basically, I think it's the upload to FTP action that is causing the problems. I need applescript to upload to the FTP and copy the url's and send the email. See attached screenshot of the workflow. I'm an applescript newbie so any help would be great.I don't know what is calling your function, but you should read the file before your call to the function and pass the contents as a byte array argument. You can process the byte array like you already do in your function.
Regards,
Marco -
just bought ipad mini. As part of set up apple sent email with link 'Verify Now'. I've clicked it repeatedly but not responding. My email account is working fine. Any ideas?
Why not just create an Apple ID for her and then you wont have any problems. Login on iMessage and Facetime using her ID and do the rest with your ID. It will work i tried it on my iPad
-
My email sent out no subject emails with links attached is this a symptom of a flashback malware.
sarahfromcypress wrote:
My email sent out no subject emails with links attached is this a symptom of a flashback malware.
Not unless they're doing something new with it. If your OS is completely up-to-date, you need not worry about Flashback in any case. -
Make your own Fax Server with Automator! (Pagesender solution for Mavericks)
I have been scouring these discussion boards for some time now looking for a suitable substitute to PageSender, an awesome fax solution for the Mac from SmileOnMyMac LLC, which for some inexplicable reason stopped development and updates after OS 10.6.8. The result is that many small business office users who still rely on fax (and yes...no matter what they tell you, most of the business world DOES still use fax because it's legally binding and more secure than email for the transmission of legal documents or healthcare records, and does not rely on database integration accross different systems, which is sadly but very realistically still a long ways off), and no longer have a way to integrate faxes into a paperless or digital workflow office system.
I suspect like many folks who receive faxes, those who used PageSender, used a very powerful feature to forward faxes by email, thereby turning your Mac into a Fax server that could distribute your faxes to other workstations and staff throughout the business via email. Presumably, if you have your own email server (Exchange, Kerio, AppleMail server, PostFix enabler etc.) you could distribute faxes on your own internal network, securely behind a firewall, and effectively create a digitial/paperless workflow for your faxes.
Even if you have a USB modem or multifunction printer that allows you to recieve a Fax to your desktop (Apple's internal fax via printer preferences, and some HP models like the HP MFP 127fw) for example will allow you to recieve a Fax to a desktop folder or forward to a single email address. But the former is of limited functionaliy and the later only lets you send to an email address out over the internet with a registered public domain, which means you give up all control of privacy and means you can't process it through a private mail server to create a digital workflow for your office...
...Until now!!!
I am happy to report that I have finally discovered a very easy and useable feature that will save a lot of time, money, and headaches for those looking to create a digital workflow and fax server system for a small office system. (I don't think there is any limit to scale here, but I suspect offices with more than 10 employees probably have a BizHub, or HP MFP/digital sender that can create the same process directly from the printer, but of course these come with a price tag of $2000 and up...).
To accomplish this however, you will need some basic requirements which are as follows:
1) A USB modem from either US Robotics or Zoom Modem. These are readily available from Amazon, MacMall or any number of other online vendors and work very well and seemlessly with all Macs running OSX right up through Mavericks
OR
A Multifunction printer that is capable of receiving faxes to a desktop Mac like the HP 127 fw. Other models exist from other manufacturers as well, but you will have to do a bit of research and probably check with the vendor or user manual directly to confirm that Fax to desktop is supported for Mac and OS 10.9.
2) A dedicated Mail Server (MSFT Exchange, Kerio, MacOSX server with mail server enabled, or PostFix enalber or MailServe from Cutedge Systems)
You will need to set up an email account on your server that is the parent for all incoming faxes from which the faxes will be sent out as part of your digital workflow. This is beyond the scope of this discussion but if you've come this far and you're still reading, you probably know how to do this already. I recommend setting this up as a POP account, not IMAP. This way, the attatchments (your faxes) will always remain on your server as a back up, until you delete them from the server.
3) Now simply go to System preferences and select "Printers and Scanners". Select either the Fax printer for your multifunction printer, or add a fax printer/reviever using the + button and select "Fax" if you are using a USB modem. You must have the USB modem attatched to the computer in order to use the built-in Apple Fax feature for the latter option.
4) Now click on the receive options. Select "Recieve faxes to this computer" and set your ring answer settings. Check "Save to" and select the designated folder (either Faxes or Shared Faxes on your computer) or create a new folder. Depending on the volume of faxes, and your back up systems, you may want to designate a separate folder on a separate drive, exclusively for your Faxes. This is where all your faxes will be stored.
5) Now launch "Automator" in your applications folder and create a new workflow. You will be presented with several options. Select "Folder Action".
6) At the top right of the window space you will see "Folder Action receives files and folders added to" . Select the Fax folder you created in step 4.
7)On the left hand side of the "Actions" menu select "Mail"
8) From the list of actions select "New Mail Message" this will take the latest Fax added to your Fax folder and attach it as a PDF to a new outgoing mail. In the "TO" address put the email address that belongs to the parent account your created for the Faxes on your mail server eg. [email protected]. In the subject field you can put "Fax Workflow" or any other generic subject that will identify to all reciptients that this is an email that contains a Fax/PDF attatchment.
Under "account" use the SMTP account you set up on your mail server to handle the routing of internal emails. In most cases, this will be the same as the parent account created above. (Effectively, this account is sending and receiving emails to itself).
9) From the list of actions, select "Send outgoing messages".
10) Save the Automator workflow with a name like "FaxDistribution" or "FaxFlow".
11) Go back to the Fax folder you created in step 4. Right click or option click on the folder and scroll down the options menu and select "Folder Actions Setup". You will see a list of scripts including the Automator workflow you just created. Choose it.
That's it!! From now on, when you get a fax, it will get dumped into the designated fax folder, and this will automatically trigger the workflow to atttach and send it as an email to anyone in your office that is set up to receive emails with the "faxserver" address. You now have a paperless fax digital workflow server system for distributing your faxes digitally to anyone in your office who needs to review your faxes. Good luck!Thank you for this interesting posting.
-
SQL query to find all suites that are associated with automation
I trying to incorporate CodeUI tests into a Release Mangement deployment template ... As a developer, I want to be able to specify a sub-tree of a test plan & only execute those test suites that are associated with automation. Is there a way to
extract all automated workitems and associated them with their respective test suites?
Any assistance would be greatly appreciated!John,
I've partially resolved the issue of executing a sub-set of suites with the following powershell implementation:
1. Extract "potential" suite paths from a XML configuration file:
<?xml version="1.0"?>
<Configurations>
<Properties>
<Property key="DEFAULT" value="SuitePaths" />
<Property key="DatabaseServer" value="MYDBSERVER" />
<Property key="DatabaseInstance" value="Default" />
<Property key="DatabaseName" value="TFS_DefaultCollection" />
<Property key="ConfigurationName" value="US - Windows 7 and IE 10" />
</Properties>
<Notifications>
<Notification key="0" value="[email protected]" />
</Notifications>
<SuitePaths>
<SuitePath key="0" value="MyProject\WebProduct\Student\Features\Login" />
<SuitePath key="1" value="MyProject\WebProduct\Student\Features\Logout" />
</SuitePaths>
<AreaPaths>
<AreaPath key="0" value="MyProject\WebProduct\Student\Features\Login" />
</AreaPaths>
</Configurations>
2. Extract record set of suites from TFS via SQL query:
# FUNCTION: Retrieve-SuitePaths
# Parameters:
# (1.) LogFile -- Name of log file (e.g., C:\Temp or C:\Temp\DEPLOY_DatabaseServer_WebCMS2_DF06_20131031.6.log)
# (2.) Connection -- Database connection
# (3.) Paths -- Hash table of suite paths
Function Retrieve-SuitePaths
param
[Parameter(Mandatory=$True)][String]$LogFile,
[Parameter(Mandatory=$True)]$Connection,
[Parameter(Mandatory=$True)]$Paths
Write-Output '--------------------------------------------------------------------------------' | Out-File -FilePath $LogFile -Append
Write-Output "Retrieve suite(s): " | Out-File -FilePath $LogFile -Append
Write-Output '--------------------------------------------------------------------------------' | Out-File -FilePath $LogFile -Append
$SuitePaths = "("
$Counter = 0
foreach ($Key in $Paths.Keys)
if ($Counter -gt 0)
$SuitePaths = $SuitePaths + ", "
$SuitePaths = $SuitePaths + "'" + $Paths.Get_Item($Key) + "'"
$Counter += 1
$SuitePaths = $SuitePaths + ")"
# --DEBUG ONLY--> Write-Output "Paths: $SuitePaths" | Out-File -FilePath $LogFile -Append
$Command = New-Object System.Data.SqlClient.SqlCommand
$SQLStatement = "
WITH
cte_SuiteChildren
AS
-- Anchor definition to pull all certify modes
SELECT
S.[SuiteId],
S.[ProjectId],
PJ.ProjectName,
S.[PlanId],
P.[Name] AS PlanName,
S.[ParentSuiteId],
S.[SuitePath],
CONVERT(NVARCHAR(256), NULL) AS ParentTitle,
S.[Title],
0 AS RecurseLevel
FROM
[dbo].[tbl_Suite] AS S
INNER JOIN [dbo].[tbl_Plan] AS P ON S.PlanID = P.PlanID
INNER JOIN [dbo].[tbl_Project] AS PJ ON S.ProjectID = PJ.ProjectID
WHERE
S.ParentSuiteID = 0
UNION ALL
-- Recursive member to pull details of certify sessions
SELECT
S.[SuiteId],
S.[ProjectId],
PJ.ProjectName,
S.[PlanId],
P.[Name] AS PlanName,
S.[ParentSuiteId],
S.[SuitePath],
PS.[Title] AS ParentTitle,
S.[Title],
SC.[RecurseLevel] + 1 AS RecurseLevel
FROM
[dbo].[tbl_Suite] AS S
INNER JOIN cte_SuiteChildren AS SC on SC.SuiteID = S.ParentSuiteID
INNER JOIN [dbo].[tbl_Suite] AS PS ON SC.SuiteId = PS.SuiteId
INNER JOIN [dbo].[tbl_Plan] AS P ON S.PlanID = P.PlanID
INNER JOIN [dbo].[tbl_Project] AS PJ ON S.ProjectID = PJ.ProjectID
cte_SuiteLevel_0
AS
SELECT
SC.[ProjectId],
SC.[PlanId],
SC.[SuiteId],
SC.[ProjectName],
SC.[PlanName],
SC.[Title],
SC.[ProjectName] + '\' + SC.[PlanName] AS Path,
SC.[RecurseLevel]
FROM
cte_SuiteChildren AS SC
WHERE
SC.[RecurseLevel] = 0
cte_SuiteLevel_1
AS
SELECT
SC.[ProjectId],
SC.[PlanId],
SC.[ParentSuiteId],
SC.[SuiteId],
SC.[ProjectName],
SC.[PlanName],
SC.[Title],
SC.[RecurseLevel]
FROM
cte_SuiteChildren AS SC
WHERE
SC.[RecurseLevel] = 1
cte_SuiteLevel_2
AS
SELECT
SC.[ProjectId],
SC.[PlanId],
SC.[ParentSuiteId],
SC.[SuiteId],
SC.[ProjectName],
SC.[PlanName],
SC.[Title],
SC.[RecurseLevel]
FROM
cte_SuiteChildren AS SC
WHERE
SC.[RecurseLevel] = 2
cte_SuiteLevel_3
AS
SELECT
SC.[ProjectId],
SC.[PlanId],
SC.[ParentSuiteId],
SC.[SuiteId],
SC.[ProjectName],
SC.[PlanName],
SC.[Title],
SC.[RecurseLevel]
FROM
cte_SuiteChildren AS SC
WHERE
SC.[RecurseLevel] = 3
cte_SuiteLevel_4
AS
SELECT
SC.[ProjectId],
SC.[PlanId],
SC.[ParentSuiteId],
SC.[SuiteId],
SC.[ProjectName],
SC.[PlanName],
SC.[Title],
SC.[RecurseLevel]
FROM
cte_SuiteChildren AS SC
WHERE
SC.[RecurseLevel] = 4
cte_SuiteLevel_5
AS
SELECT
SC.[ProjectId],
SC.[PlanId],
SC.[ParentSuiteId],
SC.[SuiteId],
SC.[ProjectName],
SC.[PlanName],
SC.[Title],
SC.[RecurseLevel]
FROM
cte_SuiteChildren AS SC
WHERE
SC.[RecurseLevel] = 5
cte_SuiteLevel_6
AS
SELECT
SC.[ProjectId],
SC.[PlanId],
SC.[ParentSuiteId],
SC.[SuiteId],
SC.[ProjectName],
SC.[PlanName],
SC.[Title],
SC.[RecurseLevel]
FROM
cte_SuiteChildren AS SC
WHERE
SC.[RecurseLevel] = 6
cte_SuiteLevel_7
AS
SELECT
SC.[ProjectId],
SC.[PlanId],
SC.[ParentSuiteId],
SC.[SuiteId],
SC.[ProjectName],
SC.[PlanName],
SC.[Title],
SC.[RecurseLevel]
FROM
cte_SuiteChildren AS SC
WHERE
SC.[RecurseLevel] = 7
cte_SuiteLevel_8
AS
SELECT
SC.[ProjectId],
SC.[PlanId],
SC.[ParentSuiteId],
SC.[SuiteId],
SC.[ProjectName],
SC.[PlanName],
SC.[Title],
SC.[RecurseLevel]
FROM
cte_SuiteChildren AS SC
WHERE
SC.[RecurseLevel] = 8
cte_SuiteLevel_9
AS
SELECT
SC.[ProjectId],
SC.[PlanId],
SC.[ParentSuiteId],
SC.[SuiteId],
SC.[ProjectName],
SC.[PlanName],
SC.[Title],
SC.[RecurseLevel]
FROM
cte_SuiteChildren AS SC
WHERE
SC.[RecurseLevel] = 9
cte_SuiteLevel_10
AS
SELECT
SC.[ProjectId],
SC.[PlanId],
SC.[ParentSuiteId],
SC.[SuiteId],
SC.[ProjectName],
SC.[PlanName],
SC.[Title],
SC.[RecurseLevel]
FROM
cte_SuiteChildren AS SC
WHERE
SC.[RecurseLevel] = 10
cte_Suites
AS
SELECT
SL0.[ProjectId],
SL0.[PlanId],
CASE
WHEN SL2.ParentSuiteId IS NULL
THEN SL1.ParentSuiteId
ELSE CASE
WHEN SL3.ParentSuiteId IS NULL
THEN SL2.ParentSuiteId
ELSE CASE
WHEN SL4.ParentSuiteId IS NULL
THEN SL3.ParentSuiteId
ELSE CASE
WHEN SL5.ParentSuiteId IS NULL
THEN SL4.ParentSuiteId
ELSE CASE
WHEN SL6.ParentSuiteId IS NULL
THEN SL5.ParentSuiteId
ELSE CASE
WHEN SL7.ParentSuiteId IS NULL
THEN SL6.ParentSuiteId
ELSE CASE
WHEN SL8.ParentSuiteId IS NULL
THEN SL7.ParentSuiteId
ELSE CASE
WHEN SL9.ParentSuiteId IS NULL
THEN SL8.ParentSuiteId
ELSE CASE
WHEN SL10.ParentSuiteId IS NULL
THEN SL9.ParentSuiteId
ELSE SL10.ParentSuiteId
END
END
END
END
END
END
END
END
END AS [ParentSuiteId],
CASE
WHEN SL2.SuiteId IS NULL
THEN SL1.SuiteId
ELSE CASE
WHEN SL3.SuiteId IS NULL
THEN SL2.SuiteId
ELSE CASE
WHEN SL4.SuiteId IS NULL
THEN SL3.SuiteId
ELSE CASE
WHEN SL5.SuiteId IS NULL
THEN SL4.SuiteId
ELSE CASE
WHEN SL6.SuiteId IS NULL
THEN SL5.SuiteId
ELSE CASE
WHEN SL7.SuiteId IS NULL
THEN SL6.SuiteId
ELSE CASE
WHEN SL8.SuiteId IS NULL
THEN SL7.SuiteId
ELSE CASE
WHEN SL9.SuiteId IS NULL
THEN SL8.SuiteId
ELSE CASE
WHEN SL10.SuiteId IS NULL
THEN SL9.SuiteId
ELSE SL10.SuiteId
END
END
END
END
END
END
END
END
END AS [SuiteId],
SL0.ProjectName,
SL0.PlanName,
--SL0.Path,
--SL1.[Title],
CASE
WHEN SL2.Title IS NULL
THEN SL0.Path + '\' + SL1.Title
ELSE CASE
WHEN SL3.Title IS NULL
THEN SL0.Path + '\' + SL1.Title + '\' + SL2.Title
ELSE CASE
WHEN SL4.Title IS NULL
THEN SL0.Path + '\' + SL1.Title + '\' + SL2.Title + '\' + SL3.Title
ELSE CASE
WHEN SL5.Title IS NULL
THEN SL0.Path + '\' + SL1.Title + '\' + SL2.Title + '\' + SL3.Title + '\' + SL4.Title
ELSE CASE
WHEN SL6.Title IS NULL
THEN SL0.Path + '\' + SL1.Title + '\' + SL2.Title + '\' + SL3.Title + '\' + SL4.Title + '\' + SL5.Title
ELSE CASE
WHEN SL7.Title IS NULL
THEN SL0.Path + '\' + SL1.Title + '\' + SL2.Title + '\' + SL3.Title + '\' + SL4.Title + '\' + SL5.Title + '\' + SL6.Title
ELSE CASE
WHEN SL8.Title IS NULL
THEN SL0.Path + '\' + SL1.Title + '\' + SL2.Title + '\' + SL3.Title + '\' + SL4.Title + '\' + SL5.Title + '\' + SL6.Title + '\' + SL7.Title
ELSE CASE
WHEN SL9.Title IS NULL
THEN SL0.Path + '\' + SL1.Title + '\' + SL2.Title + '\' + SL3.Title + '\' + SL4.Title + '\' + SL5.Title + '\' + SL6.Title + '\' + SL7.Title + '\' + SL8.Title
ELSE CASE
WHEN SL10.Title IS NULL
THEN SL0.Path + '\' + SL1.Title + '\' + SL2.Title + '\' + SL3.Title + '\' + SL4.Title + '\' + SL5.Title + '\' + SL6.Title + '\' + SL7.Title + '\' + SL8.Title + '\' + SL9.Title
ELSE SL0.Path + '\' + SL1.Title + '\' + SL2.Title + '\' + SL3.Title + '\' + SL4.Title + '\' + SL5.Title + '\' + SL6.Title + '\' + SL7.Title + '\' + SL8.Title + '\' + SL9.Title + '\' + SL10.Title
END
END
END
END
END
END
END
END
END AS Path,
CASE
WHEN SL2.RecurseLevel IS NULL
THEN SL1.RecurseLevel
ELSE CASE
WHEN SL3.RecurseLevel IS NULL
THEN SL2.RecurseLevel
ELSE CASE
WHEN SL4.RecurseLevel IS NULL
THEN SL3.RecurseLevel
ELSE CASE
WHEN SL5.RecurseLevel IS NULL
THEN SL4.RecurseLevel
ELSE CASE
WHEN SL6.RecurseLevel IS NULL
THEN SL5.RecurseLevel
ELSE CASE
WHEN SL7.RecurseLevel IS NULL
THEN SL6.RecurseLevel
ELSE CASE
WHEN SL8.RecurseLevel IS NULL
THEN SL7.RecurseLevel
ELSE CASE
WHEN SL9.RecurseLevel IS NULL
THEN SL8.RecurseLevel
ELSE CASE
WHEN SL10.RecurseLevel IS NULL
THEN SL9.RecurseLevel
ELSE SL10.RecurseLevel
END
END
END
END
END
END
END
END
END AS RecurseLevel
FROM
cte_SuiteLevel_0 AS SL0
LEFT OUTER JOIN cte_SuiteLevel_1 AS SL1 ON SL1.ParentSuiteId = SL0.SuiteId
LEFT OUTER JOIN cte_SuiteLevel_2 AS SL2 ON SL2.ParentSuiteId = SL1.SuiteId
LEFT OUTER JOIN cte_SuiteLevel_3 AS SL3 ON SL3.ParentSuiteId = SL2.SuiteId
LEFT OUTER JOIN cte_SuiteLevel_4 AS SL4 ON SL4.ParentSuiteId = SL3.SuiteId
LEFT OUTER JOIN cte_SuiteLevel_5 AS SL5 ON SL5.ParentSuiteId = SL4.SuiteId
LEFT OUTER JOIN cte_SuiteLevel_6 AS SL6 ON SL6.ParentSuiteId = SL5.SuiteId
LEFT OUTER JOIN cte_SuiteLevel_7 AS SL7 ON SL7.ParentSuiteId = SL6.SuiteId
LEFT OUTER JOIN cte_SuiteLevel_8 AS SL8 ON SL8.ParentSuiteId = SL7.SuiteId
LEFT OUTER JOIN cte_SuiteLevel_9 AS SL9 ON SL9.ParentSuiteId = SL8.SuiteId
LEFT OUTER JOIN cte_SuiteLevel_10 AS SL10 ON SL10.ParentSuiteId = SL9.SuiteId
SELECT
SS.[ProjectId],
SS.[PlanId],
SS.[ParentSuiteId],
SS.[SuiteId],
SS.[ProjectName],
SS.[PlanName],
SS.[Path],
SS.[RecurseLevel]
FROM
SELECT DISTINCT
S.[ProjectId],
S.[PlanId],
S.[ParentSuiteId],
S.[SuiteId],
S.[ProjectName],
S.[PlanName],
S.[Path],
S.[RecurseLevel]
FROM
cte_Suites AS S
WHERE
S.[RecurseLevel] IS NOT NULL
AND S.[Path] IN $($SuitePaths)
) AS SS
ORDER BY
SS.[Path]
$Command.CommandText = $SQLStatement
$Command.Connection = $Connection
$Command.CommandTimeout = 240
$DataAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$DataAdapter.SelectCommand = $Command
$DataSet = New-Object System.Data.DataSet
$DataAdapter.Fill($DataSet) | Out-Null
Write-Output "$SQLStatement" | Out-File -FilePath $LogFile -Append
# --DEBUG ONLY--> $DataSet.Tables[0]
return $DataSet
3. Execute every suite in the record set via TCM
$DataSet = ( Retrieve-SuitePaths -LogFile:$LogFile -Connection:$Connection -Path:$Paths)
# --DEBUG ONLY--> $DataSet.Tables[0].Rows.Count
# --DEBUG ONLY--> $DataSet.Tables[0]
# Determine whether or not any test suites were retrieved from TFS....
if ( $DataSet.Tables[0].Rows.Count -gt 0 )
$ListTestRunID = $null
$SumFailed = 0
$SumInconclusive = 0
foreach ($Row in $DataSet.Tables[0].Rows)
# Set project, plan & suite variables....
[Int16]$ProjectID = $Row.Item('ProjectId')
[Int16]$PlanID = $Row.Item('PlanId')
[Int16]$ParentSuiteID = $Row.Item('ParentSuiteId')
[Int16]$SuiteID = $Row.Item('SuiteId')
$ProjectName = $Row.Item('ProjectName')
$PlanName = $Row.Item('PlanName')
$Path = $Row.Item('Path')
$RecurseLevel = $Row.Item('RecurseLevel')
# Set local build path variable....
switch -wildcard ($Path)
"*WebCMS*\Administration\*"
$CUITBuildPath = $CUITPathUNC + '\WebCMS\Administration'
"*WebCMS*\Instructor\*"
$CUITBuildPath = $CUITPathUNC + '\WebCMS\Instructor'
"*WebCMS*\Student\*"
$CUITBuildPath = $CUITPathUNC + '\WebCMS\Student'
"*WebProduct*\Instructor\*"
$CUITBuildPath = $CUITPathUNC + '\WebProduct\Instructor'
"*WebProduct*\Student\*"
$CUITBuildPath = $CUITPathUNC + '\WebProduct\Student'
default
$CUITBuildPath = $CUITPathUNC
Write-Output '--------------------------------------------------------------------------------' | Out-File -FilePath $LogFile -Append
Write-Output 'Test Suite:' | Out-File -FilePath $LogFile -Append
Write-Output '--------------------------------------------------------------------------------' | Out-File -FilePath $LogFile -Append
Write-Output " ID:" | Out-File -FilePath $LogFile -Append
Write-Output " Project: $ProjectID" | Out-File -FilePath $LogFile -Append
Write-Output " Plan: $PlanID" | Out-File -FilePath $LogFile -Append
Write-Output " Parent Suite: $ParentSuiteID" | Out-File -FilePath $LogFile -Append
Write-Output " Suite: $SuiteID" | Out-File -FilePath $LogFile -Append
Write-Output " Config: $ConfigurationID" | Out-File -FilePath $LogFile -Append
Write-Output " Name:" | Out-File -FilePath $LogFile -Append
Write-Output " Project: $ProjectName" | Out-File -FilePath $LogFile -Append
Write-Output " Plan: $PlanName" | Out-File -FilePath $LogFile -Append
Write-Output " Config: $ConfigurationName" | Out-File -FilePath $LogFile -Append
Write-Output " Path:" | Out-File -FilePath $LogFile -Append
Write-Output " Suite: $Path" | Out-File -FilePath $LogFile -Append
Write-Output " Build: $CUITBuildPath" | Out-File -FilePath $LogFile -Append
# --DEBUG ONLY--> Write-Output " Recursion: $RecurseLevel" | Out-File -FilePath $LogFile -Append
Write-Output '--------------------------------------------------------------------------------' | Out-File -FilePath $LogFile -Append
# Set TCM arguements....
$ArguementPlanID = "/planid:$PlanID"
$ArguementTitle = "/title:$Title - $Path (SuiteID: $SuiteID)"
$ArguementSuiteID = "/suiteid:$SuiteID"
$ArguementConfigurationID = "/configid:$ConfigurationID"
$ArguementTFSCollection = "/collection:$TFSCollection"
$ArguementTeamProject = "/teamproject:$TFSTeamProject"
if(![string]::IsNullOrEmpty($CUITBuildPath))
$ArguementBuildDirectory = "/builddir:$CUITBuildPath"
$ArguementBuild = ""
$ArguementBuildDefinition = ""
else
$ArguementBuildDirectory = ""
$ArguementBuild = "/build:$TFSBuild"
$ArguementBuildDefinition = "/builddefinition:$BuildDefinition"
$ArguementTestEnvironment = "/testenvironment:$WebServer"
$ArguementSettingsName = ""
if(![string]::IsNullOrEmpty($SettingsName))
$ArguementSettingsName = "/settingsname:$SettingsName"
# Create test run....
Write-Host "$TCMEXE 'run' '/create' $ArguementTitle $ArguementPlanID $ArguementSuiteID $ArguementConfigurationID $ArguementTFSCollection $ArguementTeamProject $ArguementBuild $ArguementBuildDefinition $ArguementBuildDirectory $ArguementTestEnvironment $ArguementSettingsName"
Write-Output " $TCMEXE 'run' '/create' $ArguementTitle $ArguementPlanID $ArguementSuiteID $ArguementConfigurationID $ArguementTFSCollection $ArguementTeamProject $ArguementBuild $ArguementBuildDefinition $ArguementBuildDirectory $ArguementTestEnvironment $ArguementSettingsName" | Out-File -FilePath $LogFile -Append
try
$TestRunID = & $TCMEXE 'run' '/create' $ArguementTitle $ArguementPlanID $ArguementSuiteID $ArguementConfigurationID $ArguementTeamProject $ArguementTFSCollection $ArguementBuild $ArguementBuildDefinition $ArguementBuildDirectory $ArguementTestEnvironment $ArguementSettingsName
catch
$ExitMessage = $_Exception.Message
# --DEBUG ONLY--> Write-Output "TestRunID: $TestRunID" | Out-File -FilePath $LogFile -Append
if ($TestRunID -match '.+\:\s(?<TestRunID>\d+)\.')
# The test run ID is identified as a property in the match collection so we can access it directly by using the group name from the regular expression (i.e. TestRunID).
$TestRunID = $matches.TestRunID
$ArguementID = "/id:$TestRunID"
$TestRunResultsFile = $TempDirectory + "\TestRunResults$TestRunID.trx"
$ArguementQueryText = "/querytext:SELECT * FROM TestRun WHERE TestRunID=$TestRunID"
$ArguementResultsFile = "/resultsfile:""$TestRunResultsFile"""
Write-Host " Waiting for test run to complete ..."
Write-Host $TCMEXE 'run' '/list' $ArguementTeamProject $ArguementTFSCollection $ArguementQueryText
Write-Output " $TCMEXE 'run' '/list' $ArguementTeamProject $ArguementTFSCollection $ArguementQueryText" | Out-File -FilePath $LogFile -Append
$WaitingForTestRunCompletion = $true
$WaitCount= 0
while ($WaitingForTestRunCompletion)
$WaitCount = $WaitCount + 1
Write-Output " Waiting ($WaitCount)...." | Out-File -FilePath $LogFile -Append
Start-Sleep -s $TestRunWaitDelay
$TestRunStatus = & $TCMEXE 'run' '/list' $ArguementTeamProject $ArguementTFSCollection $ArguementQueryText
$TestRunStatus
if ($TestRunStatus.Count -lt 3 -or ($TestRunStatus.Count -gt 2 -and $TestRunStatus.GetValue(2) -match '.+(?<DateCompleted>\d+[/]\d+[/]\d+)'))
$WaitingForTestRunCompletion = $false
Write-Host "Evaluating test run $TestRunID results..."
# Take small pause(s) since the results might not be published yet....
Start-Sleep -s $TestRunWaitDelay
# Export results....
Write-Host $TCMEXE 'run' '/export' $ArguementID $ArguementTeamProject $ArguementTFSCollection $ArguementResultsFile
Write-Output " $TCMEXE 'run' '/export' $ArguementID $ArguementTeamProject $ArguementTFSCollection $ArguementResultsFile" | Out-File -FilePath $LogFile -Append
$WaitingForTestRunExport = $true
$WaitCount= 0
while ($WaitingForTestRunExport -and $WaitCount -lt 5)
$WaitCount = $WaitCount + 1
Write-Output " Waiting ($WaitCount)...." | Out-File -FilePath $LogFile -Append
$ExportResult = & $TCMEXE 'run' '/export' $ArguementID $ArguementResultsFile $ArguementTFSCollection $ArguementTeamProject
if ([System.IO.File]::Exists($TestRunResultsFile))
$WaitingForTestRunExport = $false
if ([System.IO.File]::Exists($TestRunResultsFile))
# Load the XML document contents.
[xml]$TestResultsXML = Get-Content "$TestRunResultsFile"
# Extract the results of the test run.
$TotalTests = $TestResultsXML.TestRun.ResultSummary.Counters.total
$PassedTests = $TestResultsXML.TestRun.ResultSummary.Counters.passed
$FailedTests = $TestResultsXML.TestRun.ResultSummary.Counters.failed
$InconclusiveTests = $TestResultsXML.TestRun.ResultSummary.Counters.inconclusive
# Output the results of the test run.
Write-Host "========== Test: $TotalTests tests ran, $PassedTests succeeded, $FailedTests failed, $InconclusiveTests inconclusive =========="
Write-Output "--------------------------------------------------------------------------------" | Out-File -FilePath $LogFile -Append
Write-Output "Summary:" | Out-File -FilePath $LogFile -Append
Write-Output "--------------------------------------------------------------------------------" | Out-File -FilePath $LogFile -Append
Write-Output " Total: $TotalTests" | Out-File -FilePath $LogFile -Append
Write-Output " Passed: $PassedTests" | Out-File -FilePath $LogFile -Append
Write-Output " Failed: $FailedTests" | Out-File -FilePath $LogFile -Append
Write-Output " Inconclusive: $InconclusiveTests" | Out-File -FilePath $LogFile -Append
$SumFailed += $FailedTests
$SumInconclusive += $InconclusiveTests
# Remove the test run results file.
[System.IO.File]::Delete($TestRunResultsFile) | Out-Null
# Add "current" TestRunID to the list of TestRunID(s)....
if ($ListTestRunID -ne $null)
$ListTestRunID = $ListTestRunID + ', '
$ListTestRunID = $ListTestRunID + $TestRunID
# Next test suite....
4. Extract record set of test runs from TFS via SQL query:
# FUNCTION: Retrieve-TestRuns
# Parameters:
# (1.) LogFile -- Name of log file (e.g., C:\Temp or C:\Temp\DEPLOY_DatabaseServer_WebCMS2_DF06_20131031.6.log)
# (2.) Connection -- Database connection
# (3.) ListTestRunID -- List of test run identifiers
Function Retrieve-TestRuns
param
[Parameter(Mandatory=$True)][String]$LogFile,
[Parameter(Mandatory=$True)]$Connection,
[Parameter(Mandatory=$True)][String]$ListTestRunID
Write-Output '--------------------------------------------------------------------------------' | Out-File -FilePath $LogFile -Append
Write-Output "Retrieve test run(s): " | Out-File -FilePath $LogFile -Append
Write-Output '--------------------------------------------------------------------------------' | Out-File -FilePath $LogFile -Append
$TestRuns = '(' + $ListTestRunID + ')'
$Command = New-Object System.Data.SqlClient.SqlCommand
$SQLStatement = "
WITH
cte_State
AS
SELECT 0 AS [StateID], 'Unspecified' AS [StateName]
UNION ALL
SELECT 1 AS [OutcomeId], 'To Be Determined (1)' AS [StateName]
UNION ALL
SELECT 2 AS [StateID], 'In Progress' AS [StateName]
UNION ALL
SELECT 3 AS [StateID], 'Completed' AS [StateName]
UNION ALL
SELECT 4 AS [StateID], 'Aborted' AS [StateName]
UNION ALL
SELECT 5 AS [OutcomeId], 'To Be Determined (5)' AS [StateName]
UNION ALL
SELECT 6 AS [StateID], 'Needs Investigation' AS [StateName]
SELECT
TR.[ProjectId] AS [Project Id],
P.[ProjectName],
TR.[TestPlanId] AS [Plan Id],
TP.Name AS [TestPlanName],
TR.[TestRunId] AS [Run Id],
TR.[Title],
S.[StateID] AS [State Id],
S.[StateName] AS [State],
TR.[StartDate] AS [Date Started],
TR.[CompleteDate] AS [Date Completed],
DATEDIFF(SECOND, TR.[StartDate], TR.[CompleteDate]) AS Duration,
TR.[Type],
TR.[IsAutomated],
TR.[TotalTests] AS [Total],
TR.[PassedTests] AS [Passed],
TR.[IncompleteTests] AS [Incomplete],
TR.[UnanalyzedTests] AS [Unanalyzed],
TR.[NotApplicableTests] AS [Not Applicable]
FROM
[Tfs_DefaultCollection].[dbo].[tbl_TestRun] AS TR
INNER JOIN [Tfs_DefaultCollection].[dbo].[tbl_Project] AS P ON TR.ProjectId = P.ProjectId
INNER JOIN [Tfs_DefaultCollection].[dbo].[tbl_Plan] AS TP ON TR.TestPlanId = TP.PlanId
INNER JOIN cte_State AS S ON TR.[State] = S.[StateID]
WHERE
TR.TestRunId IN $($TestRuns)
ORDER BY
TR.[StartDate]
$Command.CommandText = $SQLStatement
$Command.Connection = $Connection
$Command.CommandTimeout = 30
$DataAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$DataAdapter.SelectCommand = $Command
$DataSet = New-Object System.Data.DataSet
$DataAdapter.Fill($DataSet) | Out-Null
Write-Output "$SQLStatement" | Out-File -FilePath $LogFile -Append
# --DEBUG ONLY--> $DataSet.Tables[0]
return $DataSet
5. Extract record set of test results from TFS via SQL query:
# FUNCTION: Retrieve-TestRunResults
# Parameters:
# (1.) LogFile -- Name of log file (e.g., C:\Temp or C:\Temp\DEPLOY_DatabaseServer_WebCMS2_DF06_20131031.6.log)
# (2.) Connection -- Database connection
# (3.) ListTestRunID -- List of test run identifiers
Function Retrieve-TestRunResults
param
[Parameter(Mandatory=$True)][String]$LogFile,
[Parameter(Mandatory=$True)]$Connection,
[Parameter(Mandatory=$True)][String]$ListTestRunID
Write-Output '--------------------------------------------------------------------------------' | Out-File -FilePath $LogFile -Append
Write-Output "Retrieve test result(s): " | Out-File -FilePath $LogFile -Append
Write-Output '--------------------------------------------------------------------------------' | Out-File -FilePath $LogFile -Append
$TestRuns = '(' + $ListTestRunID + ')'
$Command = New-Object System.Data.SqlClient.SqlCommand
$SQLStatement = "
WITH
cte_Outcome
AS
SELECT 0 AS [OutcomeId], 'To Be Determined (0)' AS [OutcomeName]
UNION ALL
SELECT 1 AS [OutcomeId], 'In Progress' AS [OutcomeName]
UNION ALL
SELECT 2 AS [OutcomeId], 'Passed' AS [OutcomeName]
UNION ALL
SELECT 3 AS [OutcomeId], 'Failed' AS [OutcomeName]
UNION ALL
SELECT 4 AS [OutcomeId], 'Inconclusive' AS [OutcomeName]
UNION ALL
SELECT 5 AS [OutcomeId], 'To Be Determined (5)' AS [OutcomeName]
UNION ALL
SELECT 6 AS [OutcomeId], 'Aborted' AS [OutcomeName]
UNION ALL
SELECT 7 AS [OutcomeId], 'Blocked' AS [OutcomeName]
UNION ALL
SELECT 8 AS [OutcomeId], 'Not Executed' AS [OutcomeName]
UNION ALL
SELECT 10 AS [OutcomeId], 'Error' AS [OutcomeName]
UNION ALL
SELECT 11 AS [OutcomeId], 'Not Applicable' AS [OutcomeName]
UNION ALL
SELECT 12 AS [OutcomeId], 'Paused' AS [OutcomeName]
UNION ALL
SELECT 13 AS [OutcomeId], 'To Be Determined (13)' AS [OutcomeName]
UNION ALL
SELECT 255 AS [OutcomeId], 'Never Run' AS [OutcomeName]
cte_State
AS
SELECT 0 AS [StateID], 'None' AS [StateName]
UNION ALL
SELECT 1 AS [StateID], 'Ready' AS [StateName]
UNION ALL
SELECT 2 AS [StateID], 'Completed' AS [StateName]
UNION ALL
SELECT 3 AS [StateID], 'Not Ready' AS [StateName]
UNION ALL
SELECT 4 AS [StateID], 'In Progress' AS [StateName]
UNION ALL
SELECT 5 AS [StateID], 'To Be Determined' AS [StateName]
SELECT DISTINCT
TR.[TestRunId] AS [Run Id],
TR.[TestCaseId] AS [Case Id],
O.[OutcomeID] AS [Outcome Id],
O.[OutcomeName] AS [Outcome],
S.[StateID] AS [State Id],
S.[StateName] AS [State],
TR.[TestCaseTitle] AS [Title],
TR.[AutomatedTestName] AS [Automation Method],
TR.[DateStarted] AS [Date Started],
TR.[DateCompleted] AS [Date Completed],
DATEDIFF(SECOND, TR.[DateStarted], TR.[DateCompleted]) AS Duration,
TR.[FailureType] AS [Failure Type],
TR.[ErrorMessage] AS [Error]
FROM
[Tfs_DefaultCollection].[dbo].[tbl_TestResult] AS TR
INNER JOIN cte_Outcome AS O ON TR.Outcome = O.OutcomeID
INNER JOIN cte_State AS S ON TR.State = S.StateID
WHERE
TR.TestRunId IN $($TestRuns)
ORDER BY
TR.[TestRunId],
O.[OutcomeName],
TR.[TestCaseTitle]
$Command.CommandText = $SQLStatement
$Command.Connection = $Connection
$Command.CommandTimeout = 30
$DataAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$DataAdapter.SelectCommand = $Command
$DataSet = New-Object System.Data.DataSet
$DataAdapter.Fill($DataSet) | Out-Null
Write-Output '--------------------------------------------------------------------------------' | Out-File -FilePath $LogFile -Append
Write-Output "SQL Statement: " | Out-File -FilePath $LogFile -Append
Write-Output '--------------------------------------------------------------------------------' | Out-File -FilePath $LogFile -Append
Write-Output "$SQLStatement" | Out-File -FilePath $LogFile -Append
# --DEBUG ONLY--> $DataSet.Tables[0]
return $DataSet
6. Email results to distribution list
Currently, I'm simplifying the extraction of suite path ... replacing hardcoded depth with STUFF() & XML PATH
Carl. -
Hi All
We are successfully able to send email with attachment on sql prompt. The problem is when we are trying to send the attachment through Application Express after submit process its showing the attached file but without its content.
We hav created two such processes. Process one attachs the file as below
declare
file_id number;
begin
delete from dumy_file;
select nvl(max(id),0)+1 into file_id from dumy_file;
insert into dumy_file(id,name,file_obj_id,mime_type,blob_content)
select file_id, filename, id ,mime_type,blob_content
from htmldb_application_files where name = :P2_FILE;
:P2_X := file_id;
end;
And process two send the email with attachment:
declare
file_name varchar2(100);
mim_typ varchar2(50);
begin
select name into file_name from dumy_file where id = :P2_X;
select MIME_TYPE into mim_typ from dumy_file where id = :P2_X;
email_files(from_name => 'Aashu' ,
to_names => :P2_EMAIL,
subject => 'A test from APEX',
message => 'A test message from APEX',
html_message => 'A test message from APEX',
filename1 => file_name,
filetype1 => mim_typ);
end;
Here dumy_file is a custom table.
Any help would be highly appreciated.
Thanks
saurabh[rem Purpose: Sends e-mail (text and/or html, either as a string or from a file)
rem to one or more recipients (including cc and/or bcc recipients), along with
rem up to 3 file attachments (text and/or binary; default is text/plain), using
rem the UTL_SMTP package to send the e-mail, the DBMS_LOB package to read
rem binary file attachments, and the UTL_ENCODE package to convert the binary
rem attachments to BASE64 for character string (non-binary) transmission.
rem BE AWARE THAT A COMMIT MAY BE DONE BY THIS ROUTINE (see HOWEVER... below).
rem
rem The complete parameter list for the email_files procedure is shown below:
rem from_name - name and e-mail address to put in the From field
rem to_names - names and e-mail addresses for the To field (separated by
rem commas or semicolons)
rem subject - text string for Subject field
rem message - text string or text file name for Message, if any
rem html_message - html string or html file name for Message, if any
rem cc_names - names and e-mail addresses for the Cc field, if any
rem (separated by commas or semicolons)
rem bcc_names - names and e-mail addresses for the Bcc field, if any
rem (separated by commas or semicolons)
rem filename1 - first file pathname to attach, if any
rem filetype1 - mime type of first file (defaults to 'text/plain')
rem filename2 - second file pathname to attach, if any
rem filetype2 - mime type of second file (defaults to 'text/plain')
rem filename3 - third file pathname to attach, if any
rem filetype3 - mime type of third file (defaults to 'text/plain')
rem
rem Sample names and e-mail addresses are: srea (attaches @<localhost> or
rem @<mail domain>), [email protected], <[email protected]>, Steve Rea <[email protected]>,
rem and "Steve Rea" <[email protected]> (e-mail addresses must be valid - validity
rem checking is not done on them).
rem
rem A sample call in PL/SQL is shown below, which sends a text and html message,
rem plus a text file and two binary files (note: the slash after "end;" must be
rem the first character on it's line):
rem
rem begin
rem email_files(from_name => 'oracle' ,
rem to_names => '[email protected]',
rem subject => 'A test',
rem message => 'A test message',
rem html_message => '<h2>A <u><i>test</i></u> message</h2>',
rem filename1 => '/tmp/web_ptrbdca.txt',
rem filename2 => '/tmp/password_standards.pdf',
rem filetype2 => 'application/pdf',
rem filename3 => '/tmp/wb703.jpg',
rem filetype3 => 'image/jpeg');
rem end;
rem /
rem
rem If the message or html_message string has a file name in it (starting with
rem a forward slash for unix or starting with '<drive letter>:\' or '\\' for
rem Windows/DOS), the text or html file is copied into the e-mail as the message
rem or html message; otherwise, the message or html_message is copied into the
rem e-mail as-is.
rem
rem Attachment file types (mime types) that I've tested include:
rem text/plain, text/html, image/jpeg, image/gif, application/pdf,
rem application/msword
rem A list of mime types can be seen at:
rem http://www.webmaster-toolkit.com/mime-types.shtml
rem If the mime type does not begin with "text", it is assumed to be a binary
rem file that will be encoded as base64 before transmission.
rem
rem This was derived from several sources, including:
rem Dave Wotton (Cambridge UK) - mail_files.sql at
rem http://home.clara.net/dwotton/dba/oracle_smtp.htm
rem Oracle Technology Network - maildemo.sql (demo_mail) at
rem http://www.oracle.com/technology/sample_code/tech/pl_sql/htdocs/Utl_Smtp_Sample.html
rem Akadia's "Read a file word by word using DBMS_LOB" Tip at
rem http://www.akadia.com/services/read_file_with_dbms_lob.html
rem Tom Kyte of Oracle's AskTom site (http://AskTom.oracle.com) -
rem answer to "File Exists which is not a BFILE" and others.
rem
rem NOTE: The user running this must have "create any directory" and "drop any
rem directory" privileges ("create directory" was introduced in Oracle 9iR2),
rem which must be granted from a system or dba account, such as:
rem grant create any directory to scott;
rem grant drop any directory to scott;
rem then:
rem connect / as sysdba
rem grant select on dba_directories to scott;
rem or, for everyone to have directory privileges:
rem grant create any directory to public;
rem grant drop any directory to public;
rem then:
rem connect / as sysdba
rem grant select on dba_directories to public;
rem Any file in any directory accessible to the user can be attached (not just
rem the directories listed for the utl_file_dir parameter in the init.ora file).
rem HOWEVER, if you are using this to send e-mail's with attached files (or
rem reading the message text or message html from a file) from a trigger or
rem from some other SQL that you can't or don't want to have a commit done,
rem you will first need to create an Oracle directory entry for the directory
rem containing the attached files and grant read access to it to public, such
rem as:
rem create directory CESDIR_COMMON as '/home/common';
rem grant read on directory CESDIR_COMMON to public;
rem
rem You may also want to create a public synonym for this procedure, from the
rem procedure's owner:
rem create or replace public synonym email_files for email_files;
rem grant execute on email_files to public;
rem
rem FYI: I tried using the utl_file package to read binary files:
rem utl_file.get_raw(v_file_handle,data,57);
rem but got "ORA-29284: file read error" on .pdf files, so, I switched to use
rem the dbms_lob package to read binary files:
rem dbms_lob.read(v_bfile_handle,read_bytes,v_pos,data);
rem
rem Author: Stephen Rea <[email protected]>
rem University of Arkansas Cooperative Extension Service
rem Initial release: 12/21/04
rem
rem Updates:
rem 1/31/05 - Fixed for triggers and other SQL that can't have a commit by
rem checking for and using already-defined Oracle directories ("create
rem directory" is a DDL statement that does a commit).
rem 9/23/05 - Put exception handler in to handle the SMTP server being
rem down or unavailable. (Solution from Ed Siegle at Swarthmore.)
rem 7/14/06 - Additional changes to detect and handle Windows/DOS file names
rem (second and third characters ':\' for paths with drive letters, or
rem first and second characters '\\' for UNC paths).
rem 8/25/06 - Some SMTP interfaces may require angle brackets (<>) around the
rem e-mail addresses, so, add them before returning results from get_address.
rem Also, they may not attach the host if relayed through a non-localhost,
rem so, attach the mail domain part (last two components) of the relay host
rem to the address if the mail domain is not specified in the address.
rem
create or replace procedure email_files(from_name varchar2,
to_names varchar2,
subject varchar2,
message varchar2 default null,
html_message varchar2 default null,
cc_names varchar2 default null,
bcc_names varchar2 default null,
filename1 varchar2 default null,
filetype1 varchar2 default 'text/plain',
filename2 varchar2 default null,
filetype2 varchar2 default 'text/plain',
filename3 varchar2 default null,
filetype3 varchar2 default 'text/plain')
is
-- Change the SMTP host name and port number below to your own values,
-- if not localhost on port 25:
smtp_host varchar2(256) := 'localhost';
smtp_port number := 25;
-- Change the boundary string, if needed, which demarcates boundaries of
-- parts in a multi-part email, and should not appear inside the body of
-- any part of the e-mail:
boundary constant varchar2(256) := 'CES.Boundary.DACA587499938898';
recipients varchar2(32767);
directory_path varchar2(256);
file_name varchar2(256);
crlf varchar2(2):= chr(13) || chr(10);
mesg varchar2(32767);
conn UTL_SMTP.CONNECTION;
type varchar2_table is table of varchar2(256) index by binary_integer;
file_array varchar2_table;
type_array varchar2_table;
i binary_integer;
my_code number;
my_errm varchar2(32767);
-- Function to return the next email address in the list of email addresses,
-- separated by either a "," or a ";". From Oracle's demo_mail. The format
-- of mailbox may be in one of these:
-- someone@some-domain
-- "Someone at some domain" <someone@some-domain>
-- Someone at some domain <someone@some-domain>
FUNCTION get_address(addr_list IN OUT VARCHAR2) RETURN VARCHAR2 IS
addr VARCHAR2(256);
i pls_integer;
FUNCTION lookup_unquoted_char(str IN VARCHAR2,
chrs IN VARCHAR2) RETURN pls_integer IS
c VARCHAR2(5);
i pls_integer;
len pls_integer;
inside_quote BOOLEAN;
BEGIN
inside_quote := false;
i := 1;
len := length(str);
WHILE (i <= len) LOOP
c := substr(str, i, 1);
IF (inside_quote) THEN
IF (c = '"') THEN
inside_quote := false;
ELSIF (c = '\') THEN
i := i + 1; -- Skip the quote character
END IF;
GOTO next_char;
END IF;
IF (c = '"') THEN
inside_quote := true;
GOTO next_char;
END IF;
IF (instr(chrs, c) >= 1) THEN
RETURN i;
END IF;
<<next_char>>
i := i + 1;
END LOOP;
RETURN 0;
END;
BEGIN
addr_list := ltrim(addr_list);
i := lookup_unquoted_char(addr_list, ',;');
IF (i >= 1) THEN
addr := substr(addr_list, 1, i - 1);
addr_list := substr(addr_list, i + 1);
ELSE
addr := addr_list;
addr_list := '';
END IF;
i := lookup_unquoted_char(addr, '<');
IF (i >= 1) THEN
addr := substr(addr, i + 1);
i := instr(addr, '>');
IF (i >= 1) THEN
addr := substr(addr, 1, i - 1);
END IF;
END IF;
i := lookup_unquoted_char(addr, '@');
IF (i = 0 and smtp_host != 'localhost') THEN
i := instr(smtp_host, '.', -1, 2);
addr := addr || '@' || substr(smtp_host, i + 1);
END IF;
addr := '<' || addr || '>';
RETURN addr;
END;
-- Procedure to split a file pathname into its directory path and file name
-- components.
PROCEDURE split_path_name(file_path IN VARCHAR2, directory_path OUT VARCHAR2,
file_name OUT VARCHAR2) IS
pos number;
begin
-- Separate the filename from the directory name
pos := instr(file_path,'/',-1);
if pos = 0 then
pos := instr(file_path,'\',-1);
end if;
if pos = 0 then
directory_path := null;
else
directory_path := substr(file_path,1,pos - 1);
end if;
file_name := substr(file_path,pos + 1);
end;
-- Procedure to append a file's contents to the e-mail
PROCEDURE append_file(directory_path IN VARCHAR2, file_name IN VARCHAR2,
file_type IN VARCHAR2, conn IN OUT UTL_SMTP.CONNECTION) IS
generated_name varchar2(30) := 'CESDIR' || to_char(sysdate,'HH24MISS');
directory_name varchar2(30);
file_handle utl_file.file_type;
bfile_handle bfile;
bfile_len number;
pos number;
read_bytes number;
line varchar2(1000);
data raw(200);
my_code number;
my_errm varchar2(32767);
begin
begin
-- Grant access to the directory, unless already defined, and open
-- the file (as a bfile for a binary file, otherwise as a text file).
begin
line := directory_path;
select dd.directory_name into directory_name from dba_directories dd
where dd.directory_path = line and rownum = 1;
exception
when no_data_found then
directory_name := generated_name;
end;
if directory_name = generated_name then
execute immediate 'create or replace directory ' || directory_name ||
' as ''' || directory_path || '''';
execute immediate 'grant read on directory ' || directory_name ||
' to public';
end if;
if substr(file_type,1,4) != 'text' then
bfile_handle := bfilename(directory_name,file_name);
bfile_len := dbms_lob.getlength(bfile_handle);
pos := 1;
dbms_lob.open(bfile_handle,dbms_lob.lob_readonly);
else
file_handle := utl_file.fopen(directory_name,file_name,'r');
end if;
-- Append the file contents to the end of the message
loop
-- If it is a binary file, process it 57 bytes at a time,
-- reading them in with a LOB read, encoding them in BASE64,
-- and writing out the encoded binary string as raw data
if substr(file_type,1,4) != 'text' then
if pos + 57 - 1 > bfile_len then
read_bytes := bfile_len - pos + 1;
else
read_bytes := 57;
end if;
dbms_lob.read(bfile_handle,read_bytes,pos,data);
utl_smtp.write_raw_data(conn,utl_encode.base64_encode(data));
pos := pos + 57;
if pos > bfile_len then
exit;
end if;
-- If it is a text file, get the next line of text, append a
-- carriage return / line feed to it, and write it out
else
utl_file.get_line(file_handle,line);
utl_smtp.write_data(conn,line || crlf);
end if;
end loop;
-- Output any errors, except at end when no more data is found
exception
when no_data_found then
null;
when others then
my_code := SQLCODE;
my_errm := SQLERRM;
dbms_output.put_line('Error code ' || my_code || ': ' ||
my_errm);
end;
-- Close the file (binary or text)
if substr(file_type,1,4) != 'text' then
dbms_lob.close(bfile_handle);
else
utl_file.fclose(file_handle);
end if;
if directory_name = generated_name then
execute immediate 'drop directory ' || directory_name;
end if;
end;
begin
-- Load the three filenames and file (mime) types into an array for
-- easier handling later
file_array(1) := filename1;
file_array(2) := filename2;
file_array(3) := filename3;
type_array(1) := filetype1;
type_array(2) := filetype2;
type_array(3) := filetype3;
-- Open the SMTP connection and set the From and To e-mail addresses
conn := utl_smtp.open_connection(smtp_host,smtp_port);
utl_smtp.helo(conn,smtp_host);
recipients := from_name;
utl_smtp.mail(conn,get_address(recipients));
recipients := to_names;
while recipients is not null loop
utl_smtp.rcpt(conn,get_address(recipients));
end loop;
recipients := cc_names;
while recipients is not null loop
utl_smtp.rcpt(conn,get_address(recipients));
end loop;
recipients := bcc_names;
while recipients is not null loop
utl_smtp.rcpt(conn,get_address(recipients));
end loop;
utl_smtp.open_data(conn);
-- Build the start of the mail message
mesg := 'Date: ' || TO_CHAR(SYSDATE,'dd Mon yy hh24:mi:ss') || crlf ||
'From: ' || from_name || crlf ||
'Subject: ' || subject || crlf ||
'To: ' || to_names || crlf;
if cc_names is not null then
mesg := mesg || 'Cc: ' || cc_names || crlf;
end if;
if bcc_names is not null then
mesg := mesg || 'Bcc: ' || bcc_names || crlf;
end if;
mesg := mesg || 'Mime-Version: 1.0' || crlf ||
'Content-Type: multipart/mixed; boundary="' || boundary || '"' ||
crlf || crlf ||
'This is a Mime message, which your current mail reader may not' || crlf ||
'understand. Parts of the message will appear as text. If the remainder' || crlf ||
'appears as random characters in the message body, instead of as' || crlf ||
'attachments, then you''ll have to extract these parts and decode them' || crlf ||
'manually.' || crlf || crlf;
utl_smtp.write_data(conn,mesg);
-- Write the text message or message file, if any
if message is not null then
mesg := '--' || boundary || crlf ||
'Content-Type: text/plain; name="message.txt"; charset=US-ASCII' ||
crlf ||
'Content-Disposition: inline; filename="message.txt"' || crlf ||
'Content-Transfer-Encoding: 7bit' || crlf || crlf;
utl_smtp.write_data(conn,mesg);
if instr(message,'/') = 1 or instr(message,':\') = 2 or
instr(message,'\\') = 1 then
split_path_name(message,directory_path,file_name);
append_file(directory_path,file_name,'text',conn);
utl_smtp.write_data(conn,crlf);
else
utl_smtp.write_data(conn,message || crlf);
end if;
end if;
-- Write the HTML message or message file, if any
if html_message is not null then
mesg := '--' || boundary || crlf ||
'Content-Type: text/html; name="message.html"; charset=US-ASCII' ||
crlf ||
'Content-Disposition: inline; filename="message.html"' || crlf ||
'Content-Transfer-Encoding: 7bit' || crlf || crlf;
utl_smtp.write_data(conn,mesg);
if instr(html_message,'/') = 1 or instr(html_message,':\') = 2 or
instr(html_message,'\\') = 1 then
split_path_name(html_message,directory_path,file_name);
append_file(directory_path,file_name,'text',conn);
utl_smtp.write_data(conn,crlf);
else
utl_smtp.write_data(conn,html_message || crlf);
end if;
end if;
-- Append the files
for i in 1..3 loop
-- If the filename has been supplied ...
if file_array(i) is not null then
split_path_name(file_array(i),directory_path,file_name);
-- Generate the MIME boundary line according to the file (mime) type
-- specified.
mesg := crlf || '--' || boundary || crlf;
if substr(type_array(i),1,4) != 'text' then
mesg := mesg || 'Content-Type: ' || type_array(i) ||
'; name="' || file_name || '"' || crlf ||
'Content-Disposition: attachment; filename="' ||
file_name || '"' || crlf ||
'Content-Transfer-Encoding: base64' || crlf || crlf ;
else
mesg := mesg || 'Content-Type: application/octet-stream; name="' ||
file_name || '"' || crlf ||
'Content-Disposition: attachment; filename="' ||
file_name || '"' || crlf ||
'Content-Transfer-Encoding: 7bit' || crlf || crlf ;
end if;
utl_smtp.write_data(conn,mesg);
-- Append the file contents to the end of the message
append_file(directory_path,file_name,type_array(i),conn);
utl_smtp.write_data(conn,crlf);
end if;
end loop;
-- Append the final boundary line
mesg := crlf || '--' || boundary || '--' || crlf;
utl_smtp.write_data(conn,mesg);
-- Close the SMTP connection
utl_smtp.close_data(conn);
utl_smtp.quit(conn);
exception
when utl_smtp.transient_error or utl_smtp.permanent_error then
my_code := SQLCODE;
my_errm := SQLERRM;
begin
utl_smtp.quit(conn);
exception
when utl_smtp.transient_error or utl_smtp.permanent_error then
null;
end;
raise_application_error(-20000,
'Failed to send mail - SMTP server down or unavailable: Error code ' ||
my_code || ': ' || my_errm);
when others then
my_code := SQLCODE;
my_errm := SQLERRM;
raise_application_error(-20000,
'Failed to send mail: Error code ' || my_code || ': ' || my_errm);
end;
Above is the code as required by you.In my original mail I have explained that how I'm calling this procedure.
Thanks
Saurabh -
HOW TO SEND A HEBREW EMAIL WITH ATTACHMENT USING DEMO_MAIL
Hello All,
This is Not a question , just attaching something I've implemented and might be interesting for few of us,
This package I'm attaching allows to send Hebrew Language email + attaching files to it.
This package is based on demo_mail package (combined here but you can search at google for more example information if needed).
My Package is supplied as is , for any specific information regarding it , please contact me directly at : [email protected] or POST here.
* Please also note , that this package allow file to be attach via URL (meaning you will have to define a link to this file, if you would like to implement a link to a local file , e.g : c:\temp\myfile , you will have to customize the package your self with database directories option etc ...)
First I will attach an example of how to use it :
==================================
begin
demo_mail_heb.send_html_mail_attach(p_sender => '[email protected]',
p_recipients => '[email protected]',
p_subject => 'שלום וברכה עולם',
p_data => '<hr><b>בוקר טוב</b><hr>',
p_file_name => 'but_choose_file.gif',
p_file_mime_type => 'application/pdf',
p_file_URL => 'http://10.172.246.160:7777/i/but_choose_file.gif');
end;
Second Here is the Package (please note you will have to modify few settings in order to enable it , such as mail server address ..etc)
======================================================================================
CREATE OR REPLACE PACKAGE demo_mail_heb IS
----------------------- Customizable Section -----------------------
-- Customize the SMTP host, port and your domain name below.
smtp_host VARCHAR2(256) := 'mail.oracle.com';
smtp_port PLS_INTEGER := 25;
smtp_domain VARCHAR2(256) := 'oracle.com';
-- Customize the signature that will appear in the email's MIME header.
-- Useful for versioning.
MAILER_ID CONSTANT VARCHAR2(256) := 'Mailer by Oracle UTL_SMTP';
--------------------- End Customizable Section ---------------------
-- A unique string that demarcates boundaries of parts in a multi-part email
-- The string should not appear inside the body of any part of the email.
-- Customize this if needed or generate this randomly dynamically.
BOUNDARY CONSTANT VARCHAR2(256) := '-----7D81B75CCC90D2974F7A1CBD';
FIRST_BOUNDARY CONSTANT VARCHAR2(256) := '--' || BOUNDARY || utl_tcp.CRLF;
LAST_BOUNDARY CONSTANT VARCHAR2(256) := '--' || BOUNDARY || '--' ||
utl_tcp.CRLF;
-- A MIME type that denotes multi-part email (MIME) messages.
MULTIPART_MIME_TYPE CONSTANT VARCHAR2(256) := 'multipart/mixed; boundary="'||
BOUNDARY || '"';
MAX_BASE64_LINE_WIDTH CONSTANT PLS_INTEGER := 76 / 4 * 3;
-- Sent clear Html Email
procedure send_html_mail (p_sender in varchar2 default null,
p_recipients in varchar2 default null,
p_subject in varchar2 default null,
p_data in varchar2 default null,
p_mime_type in varchar2 default 'text/html; charset=windows-1255');
-- Sent Html Email with Attachment
procedure send_html_mail_attach (p_sender in varchar2 default null,
p_recipients in varchar2 default null,
p_subject in varchar2 default null,
p_data in varchar2 default '<b>áå÷ø èåá òåìí - áãé÷ä</b',
p_mime_type in varchar2 default demo_mail_heb.MULTIPART_MIME_TYPE,
p_file_name in varchar2 default 'but_choose_file.gif',
p_file_mime_type in varchar2 default 'application/pdf',
p_file_URL in varchar2 default 'http://10.172.246.160:7777/i/but_choose_file.gif');
-- A simple email API for sending email in plain text in a single call.
-- The format of an email address is one of these:
-- someone@some-domain
-- "Someone at some domain" <someone@some-domain>
-- Someone at some domain <someone@some-domain>
-- The recipients is a list of email addresses separated by
-- either a "," or a ";"
PROCEDURE mail(sender IN VARCHAR2,
recipients IN VARCHAR2,
subject IN VARCHAR2,
message IN VARCHAR2);
-- Extended email API to send email in HTML or plain text with no size limit.
-- First, begin the email by begin_mail(). Then, call write_text() repeatedly
-- to send email in ASCII piece-by-piece. Or, call write_mb_text() to send
-- email in non-ASCII or multi-byte character set. End the email with
-- end_mail().
FUNCTION begin_mail(sender IN VARCHAR2,
recipients IN VARCHAR2,
subject IN VARCHAR2,
mime_type IN VARCHAR2 DEFAULT 'text/plain',
priority IN PLS_INTEGER DEFAULT NULL)
RETURN utl_smtp.connection;
-- Write email body in ASCII
PROCEDURE write_text(conn IN OUT NOCOPY utl_smtp.connection,
message IN VARCHAR2);
-- Write email body in non-ASCII (including multi-byte). The email body
-- will be sent in the database character set.
PROCEDURE write_mb_text(conn IN OUT NOCOPY utl_smtp.connection,
message IN VARCHAR2);
-- Write email body in binary
PROCEDURE write_raw(conn IN OUT NOCOPY utl_smtp.connection,
message IN RAW);
-- APIs to send email with attachments. Attachments are sent by sending
-- emails in "multipart/mixed" MIME format. Specify that MIME format when
-- beginning an email with begin_mail().
-- Send a single text attachment.
PROCEDURE attach_text(conn IN OUT NOCOPY utl_smtp.connection,
data IN VARCHAR2,
mime_type IN VARCHAR2 DEFAULT 'text/plain',
inline IN BOOLEAN DEFAULT TRUE,
filename IN VARCHAR2 DEFAULT NULL,
last IN BOOLEAN DEFAULT FALSE);
-- Send a binary attachment. The attachment will be encoded in Base-64
-- encoding format.
PROCEDURE attach_base64(conn IN OUT NOCOPY utl_smtp.connection,
data IN RAW,
mime_type IN VARCHAR2 DEFAULT 'application/octet',
inline IN BOOLEAN DEFAULT TRUE,
filename IN VARCHAR2 DEFAULT NULL,
last IN BOOLEAN DEFAULT FALSE);
-- Send an attachment with no size limit. First, begin the attachment
-- with begin_attachment(). Then, call write_text repeatedly to send
-- the attachment piece-by-piece. If the attachment is text-based but
-- in non-ASCII or multi-byte character set, use write_mb_text() instead.
-- To send binary attachment, the binary content should first be
-- encoded in Base-64 encoding format using the demo package for 8i,
-- or the native one in 9i. End the attachment with end_attachment.
PROCEDURE begin_attachment(conn IN OUT NOCOPY utl_smtp.connection,
mime_type IN VARCHAR2 DEFAULT 'text/plain',
inline IN BOOLEAN DEFAULT TRUE,
filename IN VARCHAR2 DEFAULT NULL,
transfer_enc IN VARCHAR2 DEFAULT NULL);
-- End the attachment.
PROCEDURE end_attachment(conn IN OUT NOCOPY utl_smtp.connection,
last IN BOOLEAN DEFAULT FALSE);
-- End the email.
PROCEDURE end_mail(conn IN OUT NOCOPY utl_smtp.connection);
-- Extended email API to send multiple emails in a session for better
-- performance. First, begin an email session with begin_session.
-- Then, begin each email with a session by calling begin_mail_in_session
-- instead of begin_mail. End the email with end_mail_in_session instead
-- of end_mail. End the email session by end_session.
FUNCTION begin_session RETURN utl_smtp.connection;
-- Begin an email in a session.
PROCEDURE begin_mail_in_session(conn IN OUT NOCOPY utl_smtp.connection,
sender IN VARCHAR2,
recipients IN VARCHAR2,
subject IN VARCHAR2,
-- mime_type IN VARCHAR2 DEFAULT 'text/plain; charset=windows-1255',
mime_type IN VARCHAR2 DEFAULT 'text/plain',
priority IN PLS_INTEGER DEFAULT NULL);
-- End an email in a session.
PROCEDURE end_mail_in_session(conn IN OUT NOCOPY utl_smtp.connection);
-- End an email session.
PROCEDURE end_session(conn IN OUT NOCOPY utl_smtp.connection);
END;
CREATE OR REPLACE PACKAGE BODY demo_mail_heb IS
-- Sent clear Html Email
procedure send_html_mail (p_sender in varchar2 default null,
p_recipients in varchar2 default null,
p_subject in varchar2 default null,
p_data in varchar2 default null,
p_mime_type in varchar2 default 'text/html; charset=windows-1255')
Is
conn utl_smtp.connection;
BEGIN
conn := demo_mail_heb.begin_mail(
sender => p_sender,
recipients => p_recipients,
subject => p_subject,
mime_type => p_mime_type);
demo_mail_heb.write_text(
conn => conn,
message => p_data);
demo_mail_heb.end_mail( conn => conn );
END;
-- Sent Html Email with Attachment
procedure send_html_mail_attach (p_sender in varchar2 default null,
p_recipients in varchar2 default null,
p_subject in varchar2 default null,
p_data in varchar2 default '<b>áå÷ø èåá òåìí - áãé÷ä</b',
p_mime_type in varchar2 default demo_mail_heb.MULTIPART_MIME_TYPE,
p_file_name in varchar2 default 'but_choose_file.gif',
p_file_mime_type in varchar2 default 'application/pdf',
p_file_URL in varchar2 default 'http://10.172.246.160:7777/i/but_choose_file.gif')
is
conn utl_smtp.connection;
req utl_http.req;
resp utl_http.resp;
data RAW(200);
begin
conn := demo_mail_heb.begin_mail(
sender => p_sender,
recipients => p_recipients,
subject => p_subject,
mime_type => p_mime_type);
demo_mail_heb.attach_text(
conn => conn,
data => p_data,
mime_type => 'text/html');
demo_mail_heb.begin_attachment(
conn => conn,
mime_type => p_file_mime_type,
inline => TRUE,
filename => p_file_name,
transfer_enc => 'base64');
-- In writing Base-64 encoded text following the MIME format below,
-- the MIME format requires that a long piece of data must be splitted
-- into multiple lines and each line of encoded data cannot exceed
-- 80 characters, including the new-line characters. Also, when
-- splitting the original data into pieces, the length of each chunk
-- of data before encoding must be a multiple of 3, except for the
-- last chunk. The constant demo_mail_heb.MAX_BASE64_LINE_WIDTH
-- (76 / 4 * 3 = 57) is the maximum length (in bytes) of each chunk
-- of data before encoding.
Utl_Http.set_proxy('www-proxy.us.oracle.com', 'oracle.com');
req := utl_http.begin_request(p_file_URL);
resp := utl_http.get_response(req);
BEGIN
LOOP
utl_http.read_raw(resp, data, demo_mail_heb.MAX_BASE64_LINE_WIDTH);
demo_mail_heb.write_raw(
conn => conn,
message => utl_encode.base64_encode(data));
END LOOP;
EXCEPTION
WHEN utl_http.end_of_body THEN
utl_http.end_response(resp);
END;
demo_mail_heb.end_attachment( conn => conn );
demo_mail_heb.end_mail( conn => conn );
end;
-- Return the next email address in the list of email addresses, separated
-- by either a "," or a ";". The format of mailbox may be in one of these:
-- someone@some-domain
-- "Someone at some domain" <someone@some-domain>
-- Someone at some domain <someone@some-domain>
FUNCTION get_address(addr_list IN OUT VARCHAR2) RETURN VARCHAR2 IS
addr VARCHAR2(256);
i pls_integer;
FUNCTION lookup_unquoted_char(str IN VARCHAR2,
chrs IN VARCHAR2) RETURN pls_integer AS
c VARCHAR2(5);
i pls_integer;
len pls_integer;
inside_quote BOOLEAN;
BEGIN
inside_quote := false;
i := 1;
len := length(str);
WHILE (i <= len) LOOP
c := substr(str, i, 1);
IF (inside_quote) THEN
IF (c = '"') THEN
inside_quote := false;
ELSIF (c = '\') THEN
i := i + 1; -- Skip the quote character
END IF;
GOTO next_char;
END IF;
IF (c = '"') THEN
inside_quote := true;
GOTO next_char;
END IF;
IF (instr(chrs, c) >= 1) THEN
RETURN i;
END IF;
<<next_char>>
i := i + 1;
END LOOP;
RETURN 0;
END;
BEGIN
addr_list := ltrim(addr_list);
i := lookup_unquoted_char(addr_list, ',;');
IF (i >= 1) THEN
addr := substr(addr_list, 1, i - 1);
addr_list := substr(addr_list, i + 1);
ELSE
addr := addr_list;
addr_list := '';
END IF;
i := lookup_unquoted_char(addr, '<');
IF (i >= 1) THEN
addr := substr(addr, i + 1);
i := instr(addr, '>');
IF (i >= 1) THEN
addr := substr(addr, 1, i - 1);
END IF;
END IF;
RETURN addr;
END;
-- Write a MIME header
PROCEDURE write_mime_header(conn IN OUT NOCOPY utl_smtp.connection,
name IN VARCHAR2,
value IN VARCHAR2) IS
BEGIN
-- utl_smtp.write_data(conn, name || ': ' || value || utl_tcp.CRLF);
utl_smtp.write_raw_data(conn, UTL_RAW.CAST_TO_RAW(name || ': ' ||value || utl_tcp.CRLF));
END;
-- Mark a message-part boundary. Set <last> to TRUE for the last boundary.
PROCEDURE write_boundary(conn IN OUT NOCOPY utl_smtp.connection,
last IN BOOLEAN DEFAULT FALSE) AS
BEGIN
IF (last) THEN
utl_smtp.write_data(conn, LAST_BOUNDARY);
ELSE
utl_smtp.write_data(conn, FIRST_BOUNDARY);
END IF;
END;
PROCEDURE mail(sender IN VARCHAR2,
recipients IN VARCHAR2,
subject IN VARCHAR2,
message IN VARCHAR2) IS
conn utl_smtp.connection;
BEGIN
conn := begin_mail(sender, recipients, subject);
write_text(conn, message);
end_mail(conn);
END;
FUNCTION begin_mail(sender IN VARCHAR2,
recipients IN VARCHAR2,
subject IN VARCHAR2,
mime_type IN VARCHAR2 DEFAULT 'text/plain',
priority IN PLS_INTEGER DEFAULT NULL)
RETURN utl_smtp.connection IS
conn utl_smtp.connection;
BEGIN
conn := begin_session;
begin_mail_in_session(conn, sender, recipients, subject, mime_type,
priority);
RETURN conn;
END;
PROCEDURE write_text(conn IN OUT NOCOPY utl_smtp.connection,
message IN VARCHAR2) IS
BEGIN
utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw(CONVERT(message,'IW8ISO8859P8')));
END;
PROCEDURE write_mb_text(conn IN OUT NOCOPY utl_smtp.connection,
message IN VARCHAR2) IS
BEGIN
utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw(message));
END;
PROCEDURE write_raw(conn IN OUT NOCOPY utl_smtp.connection,
message IN RAW) IS
BEGIN
utl_smtp.write_raw_data(conn, message);
END;
PROCEDURE attach_text(conn IN OUT NOCOPY utl_smtp.connection,
data IN VARCHAR2,
mime_type IN VARCHAR2 DEFAULT 'text/plain',
inline IN BOOLEAN DEFAULT TRUE,
filename IN VARCHAR2 DEFAULT NULL,
last IN BOOLEAN DEFAULT FALSE) IS
BEGIN
begin_attachment(conn, mime_type, inline, filename);
write_text(conn, data);
end_attachment(conn, last);
END;
PROCEDURE attach_base64(conn IN OUT NOCOPY utl_smtp.connection,
data IN RAW,
mime_type IN VARCHAR2 DEFAULT 'application/octet',
inline IN BOOLEAN DEFAULT TRUE,
filename IN VARCHAR2 DEFAULT NULL,
last IN BOOLEAN DEFAULT FALSE) IS
i PLS_INTEGER;
len PLS_INTEGER;
BEGIN
begin_attachment(conn, mime_type, inline, filename, 'base64');
-- Split the Base64-encoded attachment into multiple lines
i := 1;
len := utl_raw.length(data);
WHILE (i < len) LOOP
IF (i + MAX_BASE64_LINE_WIDTH < len) THEN
utl_smtp.write_raw_data(conn,
utl_encode.base64_encode(utl_raw.substr(data, i,
MAX_BASE64_LINE_WIDTH)));
ELSE
utl_smtp.write_raw_data(conn,
utl_encode.base64_encode(utl_raw.substr(data, i)));
END IF;
utl_smtp.write_data(conn, utl_tcp.CRLF);
i := i + MAX_BASE64_LINE_WIDTH;
END LOOP;
end_attachment(conn, last);
END;
PROCEDURE begin_attachment(conn IN OUT NOCOPY utl_smtp.connection,
mime_type IN VARCHAR2 DEFAULT 'text/plain',
inline IN BOOLEAN DEFAULT TRUE,
filename IN VARCHAR2 DEFAULT NULL,
transfer_enc IN VARCHAR2 DEFAULT NULL) IS
BEGIN
write_boundary(conn);
write_mime_header(conn, 'Content-Type', mime_type);
IF (filename IS NOT NULL) THEN
IF (inline) THEN
write_mime_header(conn, 'Content-Disposition',
'inline; filename="'||filename||'"');
ELSE
write_mime_header(conn, 'Content-Disposition',
'attachment; filename="'||filename||'"');
END IF;
END IF;
IF (transfer_enc IS NOT NULL) THEN
write_mime_header(conn, 'Content-Transfer-Encoding', transfer_enc);
END IF;
utl_smtp.write_data(conn, utl_tcp.CRLF);
END;
PROCEDURE end_attachment(conn IN OUT NOCOPY utl_smtp.connection,
last IN BOOLEAN DEFAULT FALSE) IS
BEGIN
utl_smtp.write_data(conn, utl_tcp.CRLF);
IF (last) THEN
write_boundary(conn, last);
END IF;
END;
PROCEDURE end_mail(conn IN OUT NOCOPY utl_smtp.connection) IS
BEGIN
end_mail_in_session(conn);
end_session(conn);
END;
FUNCTION begin_session RETURN utl_smtp.connection IS
conn utl_smtp.connection;
BEGIN
-- open SMTP connection
conn := utl_smtp.open_connection(smtp_host, smtp_port);
utl_smtp.helo(conn, smtp_domain);
RETURN conn;
END;
PROCEDURE begin_mail_in_session(conn IN OUT NOCOPY utl_smtp.connection,
sender IN VARCHAR2,
recipients IN VARCHAR2,
subject IN VARCHAR2,
mime_type IN VARCHAR2 DEFAULT 'text/plain',
-- mime_type IN VARCHAR2 DEFAULT 'text/plain; charset=windows-1255',
priority IN PLS_INTEGER DEFAULT NULL) IS
my_recipients VARCHAR2(32767) := recipients;
my_sender VARCHAR2(32767) := sender;
BEGIN
-- Specify sender's address (our server allows bogus address
-- as long as it is a full email address ([email protected]).
utl_smtp.mail(conn, get_address(my_sender));
-- Specify recipient(s) of the email.
WHILE (my_recipients IS NOT NULL) LOOP
utl_smtp.rcpt(conn, get_address(my_recipients));
END LOOP;
-- Start body of email
utl_smtp.open_data(conn);
-- Set "From" MIME header
write_mime_header(conn, 'From', sender);
-- Set "To" MIME header
write_mime_header(conn, 'To', recipients);
-- Set "Subject" MIME header
write_mime_header(conn, 'Subject', subject);
-- Set "Content-Type" MIME header
write_mime_header(conn, 'Content-Type', mime_type);
-- Set "X-Mailer" MIME header
write_mime_header(conn, 'X-Mailer', MAILER_ID);
-- Set priority:
-- High Normal Low
-- 1 2 3 4 5
IF (priority IS NOT NULL) THEN
write_mime_header(conn, 'X-Priority', priority);
END IF;
-- Send an empty line to denotes end of MIME headers and
-- beginning of message body.
utl_smtp.write_data(conn, utl_tcp.CRLF);
IF (mime_type LIKE 'multipart/mixed%') THEN
write_text(conn, 'This is a multi-part message in MIME format.' ||
utl_tcp.crlf);
END IF;
END;
PROCEDURE end_mail_in_session(conn IN OUT NOCOPY utl_smtp.connection) IS
BEGIN
utl_smtp.close_data(conn);
END;
PROCEDURE end_session(conn IN OUT NOCOPY utl_smtp.connection) IS
BEGIN
utl_smtp.quit(conn);
END;
END;Hello All,
Small modification - use this package and not the above
HERE IS A WORKING CODE FOR SENDING HEBREW MESSAGES (INCLUDING SUBJECT IN UTF-8 APPEAR IN ALL EMAIL CLIENTS I HAVE CHECKED) + ATTACHMENTS
Code attached below is supplied as is with no support. anyhow if help is needed , please contact me via [email protected]
============================================================================
CREATE OR REPLACE PACKAGE demo_mail_heb IS
----------------------- Customizable Section -----------------------
-- Customize the SMTP host, port and your domain name below.
smtp_host VARCHAR2(256) := pst_ajax.getParameter('EMAIL_SMTP_HOST');
smtp_port PLS_INTEGER := pst_ajax.getParameter('EMAIL_SMTP_PORT');
smtp_domain VARCHAR2(256) := pst_ajax.getParameter('EMAIL_SMTP_DOMAIN');
-- Customize the signature that will appear in the email's MIME header.
-- Useful for versioning.
MAILER_ID CONSTANT VARCHAR2(256) := 'Mailer by Oracle UTL_SMTP';
--------------------- End Customizable Section ---------------------
-- A unique string that demarcates boundaries of parts in a multi-part email
-- The string should not appear inside the body of any part of the email.
-- Customize this if needed or generate this randomly dynamically.
BOUNDARY CONSTANT VARCHAR2(256) := '-----7D81B75CCC90D2974F7A1CBD';
FIRST_BOUNDARY CONSTANT VARCHAR2(256) := '--' || BOUNDARY || utl_tcp.CRLF;
LAST_BOUNDARY CONSTANT VARCHAR2(256) := '--' || BOUNDARY || '--' ||
utl_tcp.CRLF;
-- A MIME type that denotes multi-part email (MIME) messages.
MULTIPART_MIME_TYPE CONSTANT VARCHAR2(256) := 'multipart/mixed; boundary="'||
BOUNDARY || '"';
MAX_BASE64_LINE_WIDTH CONSTANT PLS_INTEGER := 76 / 4 * 3;
-- Sent clear Html Email
procedure send_html_mail (p_sender in varchar2 default null,
p_recipients in varchar2 default null,
p_subject in varchar2 default null,
p_data in varchar2 default null,
p_mime_type in varchar2 default 'text/html; charset=windows-1255');
-- Sent Html Email with Attachment
procedure send_html_mail_attach (p_sender in varchar2 default null,
p_recipients in varchar2 default null,
p_subject in varchar2 default null,
p_data in varchar2 default '<b>áå÷ø èåá òåìí - áãé÷ä</b',
p_mime_type in varchar2 default 'text/html; charset=windows-1255',
p_file_name in varchar2 default 'but_choose_file.gif',
p_file_mime_type in varchar2 default 'application/pdf',
p_file_URL in varchar2 default 'http://10.172.246.160:7777/i/but_choose_file.gif');
-- A simple email API for sending email in plain text in a single call.
-- The format of an email address is one of these:
-- someone@some-domain
-- "Someone at some domain" <someone@some-domain>
-- Someone at some domain <someone@some-domain>
-- The recipients is a list of email addresses separated by
-- either a "," or a ";"
PROCEDURE mail(sender IN VARCHAR2,
recipients IN VARCHAR2,
subject IN VARCHAR2,
message IN VARCHAR2);
-- Extended email API to send email in HTML or plain text with no size limit.
-- First, begin the email by begin_mail(). Then, call write_text() repeatedly
-- to send email in ASCII piece-by-piece. Or, call write_mb_text() to send
-- email in non-ASCII or multi-byte character set. End the email with
-- end_mail().
FUNCTION begin_mail(sender IN VARCHAR2,
recipients IN VARCHAR2,
subject IN VARCHAR2,
mime_type IN VARCHAR2 DEFAULT 'text/plain',
priority IN PLS_INTEGER DEFAULT NULL)
RETURN utl_smtp.connection;
-- Write email body in ASCII
PROCEDURE write_text(conn IN OUT NOCOPY utl_smtp.connection,
message IN VARCHAR2);
-- Write email body in non-ASCII (including multi-byte). The email body
-- will be sent in the database character set.
PROCEDURE write_mb_text(conn IN OUT NOCOPY utl_smtp.connection,
message IN VARCHAR2);
-- Write email body in binary
PROCEDURE write_raw(conn IN OUT NOCOPY utl_smtp.connection,
message IN RAW);
-- APIs to send email with attachments. Attachments are sent by sending
-- emails in "multipart/mixed" MIME format. Specify that MIME format when
-- beginning an email with begin_mail().
-- Send a single text attachment.
PROCEDURE attach_text(conn IN OUT NOCOPY utl_smtp.connection,
data IN VARCHAR2,
mime_type IN VARCHAR2 DEFAULT 'text/plain',
inline IN BOOLEAN DEFAULT TRUE,
filename IN VARCHAR2 DEFAULT NULL,
last IN BOOLEAN DEFAULT FALSE);
-- Send a binary attachment. The attachment will be encoded in Base-64
-- encoding format.
PROCEDURE attach_base64(conn IN OUT NOCOPY utl_smtp.connection,
data IN RAW,
mime_type IN VARCHAR2 DEFAULT 'application/octet',
inline IN BOOLEAN DEFAULT TRUE,
filename IN VARCHAR2 DEFAULT NULL,
last IN BOOLEAN DEFAULT FALSE);
-- Send an attachment with no size limit. First, begin the attachment
-- with begin_attachment(). Then, call write_text repeatedly to send
-- the attachment piece-by-piece. If the attachment is text-based but
-- in non-ASCII or multi-byte character set, use write_mb_text() instead.
-- To send binary attachment, the binary content should first be
-- encoded in Base-64 encoding format using the demo package for 8i,
-- or the native one in 9i. End the attachment with end_attachment.
PROCEDURE begin_attachment(conn IN OUT NOCOPY utl_smtp.connection,
mime_type IN VARCHAR2 DEFAULT 'text/plain',
inline IN BOOLEAN DEFAULT TRUE,
filename IN VARCHAR2 DEFAULT NULL,
transfer_enc IN VARCHAR2 DEFAULT NULL);
-- End the attachment.
PROCEDURE end_attachment(conn IN OUT NOCOPY utl_smtp.connection,
last IN BOOLEAN DEFAULT FALSE);
-- End the email.
PROCEDURE end_mail(conn IN OUT NOCOPY utl_smtp.connection);
-- Extended email API to send multiple emails in a session for better
-- performance. First, begin an email session with begin_session.
-- Then, begin each email with a session by calling begin_mail_in_session
-- instead of begin_mail. End the email with end_mail_in_session instead
-- of end_mail. End the email session by end_session.
FUNCTION begin_session RETURN utl_smtp.connection;
-- Handling the Email Subject Line
function mimeheader_encode(
p_str varchar2
, p_charset varchar2 := 'UTF-8') return varchar2;
-- Begin an email in a session.
PROCEDURE begin_mail_in_session(conn IN OUT NOCOPY utl_smtp.connection,
sender IN VARCHAR2,
recipients IN VARCHAR2,
subject IN VARCHAR2,
-- mime_type IN VARCHAR2 DEFAULT 'text/plain; charset=windows-1255',
mime_type IN VARCHAR2 DEFAULT 'text/plain',
priority IN PLS_INTEGER DEFAULT NULL);
-- End an email in a session.
PROCEDURE end_mail_in_session(conn IN OUT NOCOPY utl_smtp.connection);
-- End an email session.
PROCEDURE end_session(conn IN OUT NOCOPY utl_smtp.connection);
END;
CREATE OR REPLACE PACKAGE BODY demo_mail_heb IS
-- Sent clear Html Email
procedure send_html_mail (p_sender in varchar2 default null,
p_recipients in varchar2 default null,
p_subject in varchar2 default null,
p_data in varchar2 default null,
p_mime_type in varchar2 default 'text/html; charset=windows-1255')
Is
conn utl_smtp.connection;
BEGIN
conn := demo_mail_heb.begin_mail(
sender => p_sender,
recipients => p_recipients,
subject => p_subject,
mime_type => 'text/html; charset=UTF-8');--p_mime_type);
demo_mail_heb.write_text(
conn => conn,
message => p_data);
demo_mail_heb.end_mail( conn => conn );
END;
-- Sent Html Email with Attachment
procedure send_html_mail_attach (p_sender in varchar2 default null,
p_recipients in varchar2 default null,
p_subject in varchar2 default null,
p_data in varchar2 default '<b>áå÷ø èåá òåìí - áãé÷ä</b',
p_mime_type in varchar2 default 'text/html; charset=windows-1255',
p_file_name in varchar2 default 'but_choose_file.gif',
p_file_mime_type in varchar2 default 'application/pdf',
p_file_URL in varchar2 default 'http://10.172.246.160:7777/i/but_choose_file.gif')
is
conn utl_smtp.connection;
req utl_http.req;
resp utl_http.resp;
data RAW(200);
v_mime_type varchar2(32767):=demo_mail.MULTIPART_MIME_TYPE;
begin
conn := demo_mail_heb.begin_mail(
sender => p_sender,
recipients => p_recipients,
subject => p_subject,
mime_type => v_mime_type);
demo_mail_heb.attach_text(
conn => conn,
data => p_data,
mime_type => 'text/html');
demo_mail_heb.begin_attachment(
conn => conn,
mime_type => p_file_mime_type,
inline => TRUE,
filename => p_file_name,
transfer_enc => 'base64');
-- In writing Base-64 encoded text following the MIME format below,
-- the MIME format requires that a long piece of data must be splitted
-- into multiple lines and each line of encoded data cannot exceed
-- 80 characters, including the new-line characters. Also, when
-- splitting the original data into pieces, the length of each chunk
-- of data before encoding must be a multiple of 3, except for the
-- last chunk. The constant demo_mail_heb.MAX_BASE64_LINE_WIDTH
-- (76 / 4 * 3 = 57) is the maximum length (in bytes) of each chunk
-- of data before encoding.
req := utl_http.begin_request(p_file_URL);
resp := utl_http.get_response(req);
BEGIN
LOOP
utl_http.read_raw(resp, data, demo_mail_heb.MAX_BASE64_LINE_WIDTH);
demo_mail_heb.write_raw(
conn => conn,
message => utl_encode.base64_encode(data));
END LOOP;
EXCEPTION
WHEN utl_http.end_of_body THEN
utl_http.end_response(resp);
END;
demo_mail_heb.end_attachment( conn => conn );
demo_mail_heb.end_mail( conn => conn );
end;
-- Return the next email address in the list of email addresses, separated
-- by either a "," or a ";". The format of mailbox may be in one of these:
-- someone@some-domain
-- "Someone at some domain" <someone@some-domain>
-- Someone at some domain <someone@some-domain>
FUNCTION get_address(addr_list IN OUT VARCHAR2) RETURN VARCHAR2 IS
addr VARCHAR2(256);
i pls_integer;
FUNCTION lookup_unquoted_char(str IN VARCHAR2,
chrs IN VARCHAR2) RETURN pls_integer AS
c VARCHAR2(5);
i pls_integer;
len pls_integer;
inside_quote BOOLEAN;
BEGIN
inside_quote := false;
i := 1;
len := length(str);
WHILE (i <= len) LOOP
c := substr(str, i, 1);
IF (inside_quote) THEN
IF (c = '"') THEN
inside_quote := false;
ELSIF (c = '\') THEN
i := i + 1; -- Skip the quote character
END IF;
GOTO next_char;
END IF;
IF (c = '"') THEN
inside_quote := true;
GOTO next_char;
END IF;
IF (instr(chrs, c) >= 1) THEN
RETURN i;
END IF;
<<next_char>>
i := i + 1;
END LOOP;
RETURN 0;
END;
BEGIN
addr_list := ltrim(addr_list);
i := lookup_unquoted_char(addr_list, ',;');
IF (i >= 1) THEN
addr := substr(addr_list, 1, i - 1);
addr_list := substr(addr_list, i + 1);
ELSE
addr := addr_list;
addr_list := '';
END IF;
i := lookup_unquoted_char(addr, '<');
IF (i >= 1) THEN
addr := substr(addr, i + 1);
i := instr(addr, '>');
IF (i >= 1) THEN
addr := substr(addr, 1, i - 1);
END IF;
END IF;
RETURN addr;
END;
-- Write a MIME header
PROCEDURE write_mime_header(conn IN OUT NOCOPY utl_smtp.connection,
name IN VARCHAR2,
value IN VARCHAR2) IS
BEGIN
-- utl_smtp.write_data(conn, name || ': ' || value || utl_tcp.CRLF);
utl_smtp.write_raw_data(conn, UTL_RAW.CAST_TO_RAW(name || ': ' ||value || utl_tcp.CRLF));
END;
-- Mark a message-part boundary. Set <last> to TRUE for the last boundary.
PROCEDURE write_boundary(conn IN OUT NOCOPY utl_smtp.connection,
last IN BOOLEAN DEFAULT FALSE) AS
BEGIN
IF (last) THEN
utl_smtp.write_data(conn, LAST_BOUNDARY);
ELSE
utl_smtp.write_data(conn, FIRST_BOUNDARY);
END IF;
END;
PROCEDURE mail(sender IN VARCHAR2,
recipients IN VARCHAR2,
subject IN VARCHAR2,
message IN VARCHAR2) IS
conn utl_smtp.connection;
BEGIN
conn := begin_mail(sender, recipients, subject);
write_text(conn, message);
end_mail(conn);
END;
FUNCTION begin_mail(sender IN VARCHAR2,
recipients IN VARCHAR2,
subject IN VARCHAR2,
mime_type IN VARCHAR2 DEFAULT 'text/plain',
priority IN PLS_INTEGER DEFAULT NULL)
RETURN utl_smtp.connection IS
conn utl_smtp.connection;
BEGIN
conn := begin_session;
begin_mail_in_session(conn, sender, recipients, subject, mime_type,
priority);
RETURN conn;
END;
PROCEDURE write_text(conn IN OUT NOCOPY utl_smtp.connection,
message IN VARCHAR2) IS
BEGIN
utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw(CONVERT(message,'IW8ISO8859P8')));
-- utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw(message));
END;
PROCEDURE write_mb_text(conn IN OUT NOCOPY utl_smtp.connection,
message IN VARCHAR2) IS
BEGIN
utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw(message));
END;
PROCEDURE write_raw(conn IN OUT NOCOPY utl_smtp.connection,
message IN RAW) IS
BEGIN
utl_smtp.write_raw_data(conn, message);
END;
PROCEDURE attach_text(conn IN OUT NOCOPY utl_smtp.connection,
data IN VARCHAR2,
mime_type IN VARCHAR2 DEFAULT 'text/plain',
inline IN BOOLEAN DEFAULT TRUE,
filename IN VARCHAR2 DEFAULT NULL,
last IN BOOLEAN DEFAULT FALSE) IS
BEGIN
begin_attachment(conn, mime_type, inline, filename);
write_text(conn, data);
end_attachment(conn, last);
END;
PROCEDURE attach_base64(conn IN OUT NOCOPY utl_smtp.connection,
data IN RAW,
mime_type IN VARCHAR2 DEFAULT 'application/octet',
inline IN BOOLEAN DEFAULT TRUE,
filename IN VARCHAR2 DEFAULT NULL,
last IN BOOLEAN DEFAULT FALSE) IS
i PLS_INTEGER;
len PLS_INTEGER;
BEGIN
begin_attachment(conn, mime_type, inline, filename, 'base64');
-- Split the Base64-encoded attachment into multiple lines
i := 1;
len := utl_raw.length(data);
WHILE (i < len) LOOP
IF (i + MAX_BASE64_LINE_WIDTH < len) THEN
utl_smtp.write_raw_data(conn,
utl_encode.base64_encode(utl_raw.substr(data, i,
MAX_BASE64_LINE_WIDTH)));
ELSE
utl_smtp.write_raw_data(conn,
utl_encode.base64_encode(utl_raw.substr(data, i)));
END IF;
utl_smtp.write_data(conn, utl_tcp.CRLF);
i := i + MAX_BASE64_LINE_WIDTH;
END LOOP;
end_attachment(conn, last);
END;
PROCEDURE begin_attachment(conn IN OUT NOCOPY utl_smtp.connection,
mime_type IN VARCHAR2 DEFAULT 'text/plain',
inline IN BOOLEAN DEFAULT TRUE,
filename IN VARCHAR2 DEFAULT NULL,
transfer_enc IN VARCHAR2 DEFAULT NULL) IS
BEGIN
write_boundary(conn);
write_mime_header(conn, 'Content-Type', mime_type);
IF (filename IS NOT NULL) THEN
IF (inline) THEN
write_mime_header(conn, 'Content-Disposition',
'inline; filename="'||filename||'"');
ELSE
write_mime_header(conn, 'Content-Disposition',
'attachment; filename="'||filename||'"');
END IF;
END IF;
IF (transfer_enc IS NOT NULL) THEN
write_mime_header(conn, 'Content-Transfer-Encoding', transfer_enc);
END IF;
utl_smtp.write_data(conn, utl_tcp.CRLF);
END;
PROCEDURE end_attachment(conn IN OUT NOCOPY utl_smtp.connection,
last IN BOOLEAN DEFAULT FALSE) IS
BEGIN
utl_smtp.write_data(conn, utl_tcp.CRLF);
IF (last) THEN
write_boundary(conn, last);
END IF;
END;
PROCEDURE end_mail(conn IN OUT NOCOPY utl_smtp.connection) IS
BEGIN
end_mail_in_session(conn);
end_session(conn);
END;
FUNCTION begin_session RETURN utl_smtp.connection IS
conn utl_smtp.connection;
BEGIN
-- open SMTP connection
conn := utl_smtp.open_connection(smtp_host, smtp_port);
utl_smtp.helo(conn, smtp_domain);
RETURN conn;
END;
-- Handling the Email Subject Line
function mimeheader_encode(
p_str varchar2
, p_charset varchar2 := 'UTF-8') return varchar2 is
l_str varchar2(2000);
begin
l_str:=utl_raw.cast_to_varchar2(utl_encode.quoted_printable_encode(utl_raw.cast_to_raw(p_str)));
l_str:=replace(l_str,'='||chr(13)||chr(10),''); --unfold the data
l_str:=replace(l_str,'?','=3f'); --quote question marks
l_str:=replace(l_str,' ','=20'); --quote spaces
l_str:='=?'||p_charset||'?Q?'||l_str||'?='; -- add prefix and suffix
return l_str;
end;
PROCEDURE begin_mail_in_session(conn IN OUT NOCOPY utl_smtp.connection,
sender IN VARCHAR2,
recipients IN VARCHAR2,
subject IN VARCHAR2,
mime_type IN VARCHAR2 DEFAULT 'text/plain',
-- mime_type IN VARCHAR2 DEFAULT 'text/plain; charset=windows-1255',
priority IN PLS_INTEGER DEFAULT NULL) IS
my_recipients VARCHAR2(32767) := recipients;
my_sender VARCHAR2(32767) := sender;
BEGIN
-- Specify sender's address (our server allows bogus address
-- as long as it is a full email address ([email protected]).
utl_smtp.mail(conn, get_address(my_sender));
-- Specify recipient(s) of the email.
WHILE (my_recipients IS NOT NULL) LOOP
utl_smtp.rcpt(conn, get_address(my_recipients));
END LOOP;
-- Start body of email
utl_smtp.open_data(conn);
-- Set "From" MIME header
write_mime_header(conn, 'From', sender);
-- Set "To" MIME header
write_mime_header(conn, 'To', recipients);
-- Set "Content-Type" MIME header
write_mime_header(conn, 'Content-Type', mime_type);
-- write_mime_header(conn, 'Content-Type', 'text/html; charset=UTF-8');
-- Set "Subject" MIME header
-- write_mime_header(conn, 'Subject', subject);
-- write_mime_header(conn, 'Subject', CONVERT(subject,'IW8ISO8859P8'));
write_mime_header(conn, 'Subject',mimeheader_encode(p_str => subject,p_charset => 'UTF-8'));
-- write_mime_header(conn, 'Subject',CONVERT(subject,'IW8MSWIN1255'));
-- Set "X-Mailer" MIME header
write_mime_header(conn, 'X-Mailer', MAILER_ID);
-- Set priority:
-- High Normal Low
-- 1 2 3 4 5
IF (priority IS NOT NULL) THEN
write_mime_header(conn, 'X-Priority', priority);
END IF;
-- Send an empty line to denotes end of MIME headers and
-- beginning of message body.
utl_smtp.write_data(conn, utl_tcp.CRLF);
IF (mime_type LIKE 'multipart/mixed%') THEN
write_text(conn, 'This is a multi-part message in MIME format.' ||
utl_tcp.crlf);
END IF;
END;
PROCEDURE end_mail_in_session(conn IN OUT NOCOPY utl_smtp.connection) IS
BEGIN
utl_smtp.close_data(conn);
END;
PROCEDURE end_session(conn IN OUT NOCOPY utl_smtp.connection) IS
BEGIN
utl_smtp.quit(conn);
END;
END; -
Sending Email Using Automator and Mail
Every year I shave my head for a charity called St. Baldrick's. I raise money and then send pictures to all the people who donate to me shaving my head. I was wondering if there was a way to send a group of people an email with attachments in automator. Not only this but something special. Many email programs will mark something as spam if it is send to more then four people at a time. I would like to have an action or something in automator so that I can specify who to send it to and then have them sent as individual messages. This can be a real pain even if I were to copy and paste stuff. Is there a way to make my life easier so this doesn't take up so much time?
I ran accross this randomly so sorry if this is irrelevent with timing. It seems however that Text Expander might be what you need. It is a mac program though, not ios.
http://www.smilesoftware.com/TextExpander/
Maybe you are looking for
-
I cannot get Photoshop CC to work because of some Windows 8 software issue
I am trying to get my version of Photoshop CC to work on my computer. But when I do so, it always shuts down when I get a message which says "QtCorePcQt4.dll". I had tried to install a version of Picture Code (Noise Ninja) as a plug-in earlier t
-
Enabling photomerge panaorama?
I cannot access the photomerge panorama command in photoshop elements 11 on my macbook. It shows as grey. Please help?
-
PC Companion won't sync Calendar
Trying to sync my calendar manually for the first time with my phone. I'm running Windows 7 with Outlook 2007. PC Companion 2.10.226. I started the Calendar app, Calendar Sync, Sync calendar directly with my phone/tablet via USB Cable, when I get t
-
My email "reply" doesn't load. I can reply to my emails fine in other browsers.
I have a laptop pc. Web pages load okay. My email server loads okay. I can read my emails fine. However, when I attempt to reply to any email, the loading of the reply page does not complete. I cannot reply to my emails in your browser. When I use a
-
I have a new Touch 3G, model #A1318, 64GB. I can now buy/rent HD video from itunes - which as I understand it is only 720p (which is fine with me). What I can't seem to get anyone to tell me is, what resolution does the IPod Touch output to your HD T