<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Jephens Tech. &#187; sending mail</title>
	<atom:link href="http://www.jephens.com/tag/sending-mail/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.jephens.com</link>
	<description>Keeping Computers Happy Since 1997</description>
	<lastBuildDate>Tue, 22 Nov 2011 04:33:16 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=</generator>
		<item>
		<title>Filtering Mailing Lists using Access and Outlook</title>
		<link>http://www.jephens.com/2009/04/07/filtering-mailing-lists-using-access-and-outlook/</link>
		<comments>http://www.jephens.com/2009/04/07/filtering-mailing-lists-using-access-and-outlook/#comments</comments>
		<pubDate>Tue, 07 Apr 2009 15:11:17 +0000</pubDate>
		<dc:creator>Jeff Knapp</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[access]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[outlook]]></category>
		<category><![CDATA[sending mail]]></category>

		<guid isPermaLink="false">http://www.jephens.com/?p=159</guid>
		<description><![CDATA[In what is becoming a series, we'll further tweak our code to allow for filtering of the query. In the original code, we open a query directly as a recordset. This fails if the query requires some parameters. (I'm not going to demonstrate a way to get user input and use that as the parameter. [...]]]></description>
			<content:encoded><![CDATA[<p>In what is becoming a <a href="tag/sending-mail">series</a>, we'll further tweak our code to allow for filtering of the query.</p>
<p>In the <a href="http://www.jephens.com/2007/05/13/how-to-send-e-mail-from-ms-access-using-outlook">original code</a>, we open a query directly as a recordset.  This fails if the query requires some parameters.</p>
<p>(I'm not going to demonstrate a way to get user input and use that as the parameter.  You should be able to copy and paste the code from the original user input sections of the code and modify as needed.)</p>
<p>To start, let's discuss the query and it's parameter.</p>
<p>In our original code, the query was just pulling a list of email addresses.  For this, let's filter that list of addresses by domain.<br />
<span id="more-159"></span><br />
(For our purposes, I'll assume you know how to write a query with parameters.  Here's a screeenshot of how yours should look.)</p>
<p style="text-align: center;"><a href="http://www.jephens.com/wp-content/uploads/2009/04/qry1.gif"><img class="size-full wp-image-169 aligncenter" title="Parameter Query" src="http://www.jephens.com/wp-content/uploads/2009/04/qry1.gif" alt="Parameter Query" width="221" height="220" /></a></p>
<p>You can see that we added a parameter called "domain" and the told Access that we want the query to return any record that has "domain" at the end.</p>
<p>So, when we run the query from the design window, we're prompted to enter the parameter:</p>
<p style="text-align: center;"><a href="http://www.jephens.com/wp-content/uploads/2009/04/qry3.gif"><img class="size-full wp-image-171 aligncenter" title="Entered Parameter" src="http://www.jephens.com/wp-content/uploads/2009/04/qry3.gif" alt="Entered Parameter" width="260" height="219" /></a></p>
<p>and when we click RUN we'll get all email addresses from the jephens.com domain.</p>
<p>That's all well and good, but if we run the code as it exists, we get an error:</p>
<p style="text-align: center;"><a href="http://www.jephens.com/wp-content/uploads/2009/04/qry4.gif"><img class="size-full wp-image-172 aligncenter" title="Too Few Parameters" src="http://www.jephens.com/wp-content/uploads/2009/04/qry4.gif" alt="Too Few Parameters" width="223" height="121" /></a></p>
<p>This occurs because the code doesn't know what to do with the parameter, so it punts and throws an error.</p>
<p>We'll need to handle this.  And for that, we have to use a <strong>QueryDef</strong> object and assign a <strong>parameter</strong>.</p>
<p>So, instead of:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">Set</span> MailList = db.<span class="me1">OpenRecordset</span><span class="br0">&#40;</span><span class="st0">&quot;MyEmailAddresses&quot;</span><span class="br0">&#41;</span></div>
<p>... we need to do a few things:</p>
<p>1. Create a QueryDef object</p>
<p>2 Assign our query to the object</p>
<p>3. Tell the object what our parameter is</p>
<p>4. Put the output of our query into our recordset.</p>
<p>Happily, this is pretty simple.</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">Dim</span> qryMail <span class="kw1">as</span> <span class="kw1">QueryDef</span></p>
<p><span class="kw1">Set</span> qryMail = currentdb.<span class="me1">querydefs</span><span class="br0">&#40;</span><span class="st0">&quot;MyEmailAddresses&quot;</span><span class="br0">&#41;</span></p>
<p>qryMail<span class="br0">&#40;</span><span class="st0">&quot;domain&quot;</span><span class="br0">&#41;</span> = <span class="st0">&quot;.com&quot;</span></p>
<p><span class="kw1">Set</span> MailList = qryMail.<span class="me1">OpenRecordset</span></div>
<p>And that will filter the recordset and only send mails to people in the .com namespace.</p>
<p>Of course, that's not the most user-friendly code, so you'd probably want to copy and paste some of the user input language and use that to fill in the parameter:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">Dim</span> Domain <span class="kw1">as</span> <span class="kw1">string</span>, qryMail <span class="kw1">as</span> <span class="kw1">QueryDef</span></p>
<p>Domain$ = <span class="kw1">InputBox</span>$<span class="br0">&#40;</span><span class="st0">&quot;Please enter domain you would like to filter. Leave blank to send to everyone on the list.&quot;</span>, <span class="st0">&quot;Users can be choosers!&quot;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">Set</span> qryMail = currentdb.<span class="me1">querydefs</span><span class="br0">&#40;</span><span class="st0">&quot;MyEmailAddresses&quot;</span><span class="br0">&#41;</span></p>
<p>qryMail<span class="br0">&#40;</span><span class="st0">&quot;domain&quot;</span><span class="br0">&#41;</span> = domain$</p>
<p><span class="kw1">Set</span> MailList = qryMail.<span class="me1">OpenRecordset</span></div>
<p>The nice thing about the way we wrote the query is we can leave the domain part blank, and the query will return all the records.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jephens.com/2009/04/07/filtering-mailing-lists-using-access-and-outlook/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Using Access and Outlook to Send To Mailing Lists</title>
		<link>http://www.jephens.com/2009/03/15/using-access-and-outlook-to-send-to-mailing-lists/</link>
		<comments>http://www.jephens.com/2009/03/15/using-access-and-outlook-to-send-to-mailing-lists/#comments</comments>
		<pubDate>Sun, 15 Mar 2009 22:31:57 +0000</pubDate>
		<dc:creator>Jeff Knapp</dc:creator>
				<category><![CDATA[Productivity]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[access]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[office]]></category>
		<category><![CDATA[outlook]]></category>
		<category><![CDATA[sending mail]]></category>

		<guid isPermaLink="false">http://www.jephens.com/?p=131</guid>
		<description><![CDATA[Perhaps the most popular article on the site explains how to send email to a bunch of people using Access and Outlook. It has garnered its fair share of comments and emails, and one came in today that I figured I'd share and then elaborate on. The mail reads (in part): I have a following [...]]]></description>
			<content:encoded><![CDATA[<p>Perhaps the most popular article on the site <a href="http://www.jephens.com/2007/05/13/how-to-send-e-mail-from-ms-access-using-outlook">explains how to send email to a bunch of people using Access and Outlook</a>.</p>
<p>It has garnered its fair share of comments and emails, and one came in today that I figured I'd share and then elaborate on.</p>
<p>The mail reads (in part):</p>
<p style="padding-left: 30px; "><em>I have a following question: How to modify this module to be able to send messages to various mailing lists that I predefine in respective queries? In other words, I have in my database 3 categories of customers (in 3 different queries) andI want to address them with a different message. Do I need to create 3 macros running 3 modules each referring to a separate query with a given category of customers or is there another way to do it?</em></p>
<p>You don't have to create modules for each list, you just need to be able to tell the macro which query you want to use before running it.<br />
<span id="more-131"></span><br />
There's a few different ways to do it:</p>
<ol>
<li>Edit the code to reflect the list each time you want to run the macro</li>
<li>Have the code ask you which query you want to use</li>
<li>Set up different macros to do the work for you.</li>
</ol>
<p>Let's take a look at the various ways...</p>
<h2>1. Edit the code</h2>
<p>The first one is pretty self-explanatory, so I won't elaborate much. Just change the line:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw1">Dim</span> qryName <span class="kw1">as</span> <span class="kw1">String</span></p>
<p>qryName = <span class="kw1">InputBox</span>$<span class="br0">&#40;</span><span class="st0">&quot;Please enter the name of the query you want to use to get the addresses&quot;</span>, <span class="st0">&quot;Which Addresses?&quot;</span><span class="br0">&#41;</span></p>
<p><span class="co1">' If there€™s no one to write to, call it a day.</span></p>
<p><span class="kw1">If</span> qryName$ = <span class="st0">&quot;&quot;</span> <span class="kw1">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">MsgBox</span> <span class="st0">&quot;Without addresses, we can't send a message.&quot;</span> &amp;amp; <span class="kw1">vbNewLine</span> &amp;amp; <span class="kw1">vbNewLine</span> &amp;amp; <span class="st0">&quot;Quitting...&quot;</span>, <span class="kw1">vbCritical</span>, <span class="st0">&quot;No one to send to...&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">Exit</span> <span class="kw1">Function</span><br />
<span class="kw1">End</span> <span class="kw1">If</span></p>
<p><span class="kw1">Set</span> MailList = db.<span class="me1">OpenRecordset</span><span class="br0">&#40;</span>qryName<span class="br0">&#41;</span></div>
<p><strong>NOTICE</strong> that there are <strong>NO QUOTES</strong> around <em>qryName</em> like we had around "MyEMailAddresses" -- since <em>qryName</em> is a variable and will be replaced by whatever we typed in the box, it doesn't get quotes around it.</p>
<p>Also note, that we're not checking to make sure the query is correct, we trust you to get it right and not make a typo. <img src='http://www.jephens.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Lastly, we need to ensure that the queries we're using to seed this thing have the same fields as the query we're replacing, otherwise errors will be thrown... to clarify, if your new query has a field named "E-Mail" and we're looking for a field called "Email" -- the routine will fail.</p>
<h2>3. Use a macro to fill the query in for you</h2>
<p>This is the coolest way to do it, since you only have to make the macro once, and then you can run it as many times as you want with no more effort than a double-click.</p>
<p>We need a way to tell the Function that we want to use a specific query. The way we do this is by using an <strong>ARGUMENT</strong>.</p>
<p>The first line of our function looks like this:</p>
<pre class="prettyprint"> Public Function SendEMail()</pre>
<p>The parentheses at the end are where we put the arguments. In our initial example, we didn't need any arguments, so the parens were empty... but now we want to use an argument. An argument is nothing more than a variable that is filled in before hand. In Option 2, we typed the queryname in every time we ran the macro. We're going to change the irst line of our function AND we're going to change the line that assigns the query like so:</p>
<pre class="prettyprint"> Public Function SendEMail(qryName as String)</pre>
<p>See what we did there? We took the variable declaration from the 2nd option (<em>Dim qryName as String</em>), and put in the argument field instead.</p>
<p>Now, in the meat of the routine, we need to change one line from:</p>
<pre class="prettyprint"> Set MailList = db.OpenRecordset("MyEmailAddresses")</pre>
<p>to</p>
<pre class="prettyprint"> Set MailList = db.OpenRecordset(qryName)</pre>
<p>(Look a little familiar?)</p>
<p>So, now we have our function edited, but where do we put the query name we want to use? <em>In the macro</em>.</p>
<h3>Running the Macro</h3>
<p>If we run the macro we wrote in the first article, we're going to get an error since it doesn't provide an argument.</p>
<p><img class="alignnone size-full wp-image-140" title="macro4" src="http://www.jephens.com/wp-content/uploads/2009/03/macro4.gif" alt="macro4" width="403" height="86" /></p>
<p>So, we need to edit the macro.</p>
<p>Go into the macro definition, and it looks like this:<img class="alignnone size-full wp-image-137" title="macro1" src="http://www.jephens.com/wp-content/uploads/2009/03/macro1.gif" alt="macro1" width="564" height="296" /></p>
<p>And where it says "=SendEmail()" is where we're going to make our edit.</p>
<p>Since we want this macro to work like it always did, we need to use query we wrote for the original article, which is called<strong>MyEMailAddresses.</strong></p>
<p>We need to update the function name to <em>=SendEmail("MyEmailAddresses") </em>like so:</p>
<p><img class="alignnone size-full wp-image-138" title="macro2" src="http://www.jephens.com/wp-content/uploads/2009/03/macro2.gif" alt="macro2" width="389" height="70" /></p>
<p>If you wanted, you could also use the Expression Builder by clicking the button with 3 dots on it to pick your function name. This is what that looks like:</p>
<p><img class="alignnone size-full wp-image-139" title="macro3" src="http://www.jephens.com/wp-content/uploads/2009/03/macro3.gif" alt="macro3" width="406" height="410" /></p>
<p>So you can see that the function (SendEmail) is now asking for an argument (the bit in the parentheses) called <strong>qryName</strong>.</p>
<p>Now, if you save the macro and run it, the macro should run like always.</p>
<p>To make a different macro for each of your queries, just copy the macro we made...</p>
<p><img class="alignnone size-full wp-image-143" title="macro5" src="http://www.jephens.com/wp-content/uploads/2009/03/macro5.gif" alt="macro5" width="346" height="278" /></p>
<p>... and paste it with a new name:</p>
<p><img class="alignnone size-full wp-image-142" title="macro6" src="http://www.jephens.com/wp-content/uploads/2009/03/macro6.gif" alt="macro6" width="270" height="112" /></p>
<p>And that's all there is to it.</p>
<p>Any time you need to send to a new list, write a new query, copy, paste then edit the macro and you're off to the races.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jephens.com/2009/03/15/using-access-and-outlook-to-send-to-mailing-lists/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>How to Send E-Mail From MS Access using Outlook</title>
		<link>http://www.jephens.com/2007/05/13/how-to-send-e-mail-from-ms-access-using-outlook/</link>
		<comments>http://www.jephens.com/2007/05/13/how-to-send-e-mail-from-ms-access-using-outlook/#comments</comments>
		<pubDate>Sun, 13 May 2007 21:13:12 +0000</pubDate>
		<dc:creator>Jeff Knapp</dc:creator>
				<category><![CDATA[Productivity]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[access]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[office]]></category>
		<category><![CDATA[outlook]]></category>
		<category><![CDATA[sending mail]]></category>

		<guid isPermaLink="false">http://10.20.30.112/?p=19</guid>
		<description><![CDATA[Click here for the changelog. (I moved it to the bottom of the page.) Microsoft Office is designed to work together in an effort to help users get their work done more efficiently. To this end, Microsoft has given all the pieces of the Office suite the ability to control or be controlled by other [...]]]></description>
			<content:encoded><![CDATA[<p class="tiny"><a href="#changelog">Click here for the changelog.  (I moved it to the bottom of the page.)</a></p>
<p>Microsoft Office is designed to work together in an effort to help users get their work done more efficiently.  To this end, Microsoft has given all the pieces of the Office suite the ability to control or be controlled by other of its Office siblings through the use of Visual Basic for Applications. (VBA)  VBA is result of the merging of Visual Basic and the macro languages originally designed for the individual applications that now make up office.  Finally, with Office97, all applications share a common macro language... and with that, we can use Access to store our e-mail addresses and use Outlook to send them... and we don't have to do anything in the middle beyond writing a query, a simple routine and a macro to make it all happen.</p>
<p class="tiny"><strong>NOTE: The Outlook Security Patch (it comes with Office 2000 SR-2, OfficeXP or as a seperate "security" download) makes this exercise just this side of useless.  Since virus writers use these same techniques to send e-mail without you knowing, Microsoft instead pops up a dialog box for 3-5 seconds PER ADDRESS so the virus writer can't take advantage of you.  Of course, YOU can't take advantage of this power any longer, since MS thinks you're unable to protect yourself.  *sigh* Perhaps one of these days I will write an article explaining how to do this using a freeware mail component...</strong></p>
<p class="tiny"><strong>You can get around the security model if you're willing to spend a little money.  Check out the <a href="http://www.dimastr.com/redemption/">Redemption object model</a>. It's more or less a rewrite of the Outlook model, but bypasses the security triggers.  However, it's $200 if you want to use it anywhere, and it does require installing a DLL on the client machine... if your IT policy doesn't allow for that, you're out of luck.</strong></p>
<p class="tiny">This code doesn't work with Redemption -- the theory does, but the actual code doesn't.  Maybe someday I'll make a "Redemption" page, but I just don't have the time right now.  (If anyone wants to convert it, lemme know, and I'll post your article.)</p>
<p class="tiny">Here's a page with some links about the security model: <a href="http://www.granite.ab.ca/access/email/outlook.htm">http://www.granite.ab.ca/access/email/outlook.htm</a></p>
<p>You can download the sample database in either <a href="/email.mdb">Access97 (128k)</a>, <a href="/email2k.mdb">Access2000 (132k)</a> or <a href="/email02.mdb">Access2002 (164k)</a> format.  You can then just import the query and module into your own database and skip the cutting and pasting.  I'm going to assume you have a basic understanding how Access works, and can make a query.</p>
<h2>The Query</h2>
<p>You have a table that has a list of email addresses.  (If you didn't, you'd be reading something else, I'm sure!)  You want to send all the people in the list an e-mail... so we need to use a query to get the e-mail addresses we want.  Open a new query and add the table that has the email addresses you want.  Select the field with the email addresses and call it "EMail".  If the field that holds your email addresses is called anything other than "EMail" you can force it to be referred to as "Email" by putting "EMail:" in fromt of the field name in the query grid.  You can also add any other fields you want for purposes of filtering and whatnot.  We're only concerned with the field known as "email"  Once you get the query the way you like it, save it as "MyEmailAddresses"</p>
<h2>The Body</h2>
<p>To keep things as generic as possible, I grab the body of the e-mail from a text file.  That way, you can just change the text file and not have to touch any of this code again.  There are other ways to do this (like storing the body in the database, for instance) but using an external file allows us to look at how to grab text from a file; another handy skill to have.  So, when you run the macro, it will ask you for the full path of the text file you just created with the body text in it.</p>
<h2>The Macro</h2>
<p>Macros provide easy ways to trigger code or run actions.  In our case, we'll use it to trigger some code we're going to write.  The nice thing is, we can make the macro first... tho the macro won't work until we write the code.  So, let's make a macro.</p>
<ol>
<li>Click on the macro tab and create a new macro.</li>
<li>In the action column, choose "RunCode"</li>
<li>In the spot down below where it asks for the function name, type =SendEMail()</li>
<li>Save the macro.</li>
</ol>
<h2>The Module</h2>
<p>Now, we need to add some code to our database to let it talk to Outlook and send our mail.  We do this by clicking on the module tab and adding a new module.  After you cut and paste the code in, save the module.  The name is irrelevant, but I try and group related things together in a module, so I recommend calling it "SendMail" or something similar.  The other thing you need to do is set some references to the Outlook object model and the Scripting runtime.  The Outlook Object Model is what allows Access to talk Outlook easily, and the scripting runtime allows you manipulate and read files.  To set the references you need to check off a few boxes... here's how.</p>
<ol>
<li>In the module, click on <strong>Tools</strong> then <strong>References</strong></li>
<li>Scroll down the list and place a checkmark next to <strong>Outlook x.0 Object Model</strong> (for Outlook 98 it is version 8.0, Outlook 2000 is version 9.0, Outlook 2002/XP is version 10.0)</li>
<li>If it wasn't already checked near the top, scroll down a little bit more and check <strong>Microsoft DAO 3.x Object Library</strong></li>
<li>Scroll down a little bit more and check <strong>Microsoft Scripting Runtime</strong></li>
<li>Click OK to close that window.</li>
</ol>
<p>Failure to do the above will result in "User Defined Type not defined" errors.  (There's a chance that on newer systems DAO may not be installed.  If that's the case, then you're out of luck until I can update this article with the newer ADO code.  Tho the concepts are still the same, this code worn't work. Sorry.)  You can get the DAO libraries as part of the Jet 4.0 Engine.  <a href="http://support.microsoft.com/kb/239114">Grab the latest service pack from Microsoft.</a></p>
<h2>The Explanation</h2>
<p>The code is pretty well commented, but this is what it does in English.  The code opens Outlook and opens your query.  It asks you for the subject line to use and the text file to use for the body of the message.  The code then creates a message, addresses it and sends it to each person in your list that made it through gauntlet known as "MyEMailAddresses."  Many people keep Outlook running all the time, so this routine will not shut it down when it's done running unless you uncomment the line (remove the ') that says MyOutlook.Quit.  Now, let's get this code into the module and call it a day.</p>
<h2>The Code</h2>
<p>Copy and paste the following code into the Access code module:</p>
<pre class="code prettyprint lang-vb" style="height: 60em;">Public Function SendEMail()

Dim db As DAO.Database
Dim MailList As DAO.Recordset
Dim MyOutlook As Outlook.Application
Dim MyMail As Outlook.MailItem
Dim Subjectline As String
Dim BodyFile As String
Dim fso As FileSystemObject
Dim MyBody As TextStream
Dim MyBodyText As String

Set fso = New FileSystemObject

' First, we need to know the subject.

' We canï¿½ï¿½t very well be sending around blank messages...

Subjectline$ = InputBox$("Please enter the subject line for this mailing.", _
"We Need A Subject Line!")

' If thereï¿½ï¿½s no subject, call it a day.

If Subjectline$ = "" Then
MsgBox "No subject line, no message." &amp; vbNewLine &amp; vbNewLine &amp; _
"Quitting...", vbCritical, "E-Mail Merger"
Exit Function
End If

' Now we need to put something in our letter...

BodyFile$ = InputBox$("Please enter the filename of the body of the message.", _
"We Need A Body!")

' If thereï¿½ï¿½s nothing to say, call it a day.

If BodyFile$ = "" Then
MsgBox "No body, no message." &amp; vbNewLine &amp; vbNewLine &amp; _
"Quitting...", vbCritical, "I Ainï¿½ï¿½t Got No-Body!"
Exit Function
End If

' Check to make sure the file exists...
If fso.FileExists(BodyFile$) = False Then
MsgBox "The body file isnï¿½ï¿½t where you say it is. " &amp; vbNewLine &amp; vbNewLine &amp; _
"Quitting...", vbCritical, "I Ainï¿½ï¿½t Got No-Body!"
Exit Function
End If

' Since we got a file, we can open it up.
Set MyBody = fso.OpenTextFile(BodyFile, ForReading, False, TristateUseDefault)

' and read it into a variable.
MyBodyText = MyBody.ReadAll

' and close the file.
MyBody.Close

' Now, we open Outlook for our own device..
Set MyOutlook = New Outlook.Application

' Set up the database and query connections

Set db = CurrentDb()

Set MailList = db.OpenRecordset("MyEmailAddresses")

' now, this is the meat and potatoes.
' this is where we loop through our list of addresses,
' adding them to e-mails and sending them.

Do Until MailList.EOF

' This creates the e-mail

Set MyMail = MyOutlook.CreateItem(olMailItem)

' This addresses it

MyMail.To = MailList("email")

'This gives it a subject
MyMail.Subject = Subjectline$

'This gives it the body
MyMail.Body = MyBodyText

'If you want to send an attachment
'uncomment the following line

'MyMail.Attachments.Add "c:myfile.txt", olByValue, 1, "My Displayname"

' To briefly describe:
' "c:myfile.txt" = the file you want to attach
'
' olByVaue = how to pass the file. olByValue attaches it, olByReference creates a shortcut.
' the shortcut only works if the file is available locally (via mapped or local drive)
'
' 1 = the position in the outlook message where to attachment goes. This is ignored by most
' other mailers, so you might want to ignore it too. Using 1 puts the attachment
' first in line.
'
' "My Displayname" = If you donï¿½ï¿½t want the attachmentï¿½ï¿½s icon string to be "c:myfile.txt" you
' can use this property to change it to something useful, i.e. "4th Qtr Report"

'This sends it!

MyMail.Send

'Some people have asked how to see the e-mail
'instead of automaticially sending it.
'Uncomment the next line
'And comment the "MyMail.Send" line above this.

'MyMail.Display

'And on to the next one...
MailList.MoveNext

Loop

'Cleanup after ourselves

Set MyMail = Nothing

'Uncomment the next line if you want Outlook to shut down when its done.
'Otherwise, it will stay running.

'MyOutlook.Quit
Set MyOutlook = Nothing

MailList.Close
Set MailList = Nothing
db.Close
Set db = Nothing

End Function</pre>
<h2>Further Options</h2>
<p>The sky is really the limit as to what you can do.</p>
<p>I've been asked about "personalizing" the text with data from the database a few times, so after I wrote my variation on the reply, I thought I'd add it to the page.  It's not particularly hard, but it requires some planning and special markups in the text file you're using as the body.</p>
<p>If you need something as simple as a greeting line, all you have to do is change one line:</p>
<p>The big difference would be to change the MyMail.Body from your text file to something else that would have the "Hi Joe!" in it.</p>
<pre class="code prettyprint lang-vb" style="height: 2em;">MyMail.Body = MyBodyText</pre>
<p>becomes</p>
<pre class="code prettyprint lang-vb" style="height: 5em;">MyMail.Body = "Hi " &amp; MailList("FirstName") &amp; "!" &amp; vbNewLine &amp; vbNewLine &amp; MyBodyText</pre>
<p>vbNewLine puts a hard return at the end of the line, so two of them give you in essence, a paragraph break before the text from your template.</p>
<p>To get a little more complicated, you can "tokenize" the text you want to replace.</p>
<p>Since the text of your e-mail is just a string, you can manipulate that string however you want.  You could make what we call "tokens" in the template, and then use string manipulation functions to replace the tokens with fields from your database.</p>
<p>For instance, say you want the text of your e-mail to read:  "Joe: Yesterday, you sold 20 widgets. You did good!"</p>
<p>You can't just have a text file that says that, otherwise everyone in your database would know that Joe sold 20 widgets (Good for Joe!), and they'd have no idea about their own performance, so we need to create tokens.</p>
<p>So, we need to place specific words or phrases with generic ones:</p>
<pre class="code prettyprint lang-vb" style="height: 5em;">[[Firstname]]: Yesterday, you sold [[NumberOfUnits]] widgets. [[GoodOrBad]]</pre>
<p>Then, in the loop that goes thru the names, we'd need to replace the tokens with the values from the database... However, once we replaced it the first time, we'd lose our token (it was replaced the first go-round) so we need to create a new varibale to hold our custom-per-message body:</p>
<pre class="code prettyprint lang-vb" style="height: 15em;">' This line will copy the "master" template into
' a variable we can mess around with

MyNewBodyText = MyBodyText

' Now we can replace tokens to our heart's content
' without worrying about corrupting the "master" template

MyNewBodyText = Replace(MyNewBodyText, "[[FirstName]]", MailList("FirstName"))

MyNewBodyText = Replace(MyNewBodyText, "[[NumberOfUnits]]", MailList("NumberofUnits"))</pre>
<p>that would then replace the tokens [[Firstname]] and [[NumberOfUnits]] with their values from the database.</p>
<p>A token can be any sequence of characters that won't be repeated by accident.  So, you could use the word "you" as a token, but every time it was encountered in the document, whether or not it was meant to, it would be replaced by the new value.</p>
<p>(i.e the above desired sentence would become "Yesterday 20 sold [[NumberOfUnits]] widgets. 20 did good!" -- not the result you were hoping for...)</p>
<p>So, we create tokens that are unique -- I use two open brackets, a descriptive string, and two closing brackets -- that sequence of characters won't occur anywhere else by accident, so I can be confident that I won't accidentally create a sentence like the above.</p>
<p>You can also add all sorts of logic to things.</p>
<p>For instance, instead of everyone getting the "You did good!" you might use the token [[GoodOrBad]] and then use a logic statement like:</p>
<pre class="code prettyprint lang-vb" style="height: 10em;">If MailList("NumberOfUnits") &gt; 20 then
MyBodyText = Replace(MyNewBodyText, "[[GoodOrBad]]", "You did good!")
else
MyBodyText = Replace(MyNewBodyText, "[[GoodOrBad]]", "You stink!")
End If</pre>
<p>... which would text of the person made a quota, and offer a value statement based on his performance.</p>
<p>(Of course, remember to then change your variable name when you assign the body to it --</p>
<pre class="code prettyprint lang-vb" style="height: 5em;">MyMail.Body = MyNewBodyText</pre>
<h2>Conclusion</h2>
<p>There's so much you can do with this simple routine... I enjoy hearing from you (and getting your test messages!) and am glad we can help you out this way.</p>
<h2>Here's something else...</h2>
<p>Someone asked me about tracking the e-mails sent in a table in the database.  Since its on my mind, here's what I wrote:</p>
<p>You would open the table, and after each e-mail, append a record:</p>
<pre class="code prettyprint lang-vb" style="height: 12em;">[Near the top of the code]

Dim MyTrackingTable as Recordset
Set MyTrackingTable = Currentdb.OpenRecordset("TrackingTableName")</pre>
<p>[later on in the code, after MyMail.Send]</p>
<pre class="code prettyprint lang-vb" style="height: 12em;">MyTrackingTable.AddNew
MyTrackingTable("emailaddress") = MyMail.To
MyTrackingTable("emailsubject") = MyMail.Subject
MyTrackingTable("DateSent") = now()
MyTrackingTable.Update</pre>
<p>[back to code]</p>
<pre class="code prettyprint lang-vb" style="height: 12em;">    'And on to the next one...
    MailList.MoveNext

Loop

[etc.]</pre>
<p>So, obviously, you'll need a table with three fields in it, emailaddress, emailsubject and datesent.  You can then tweak this table setup as you see fit.</p>
<h2>More Recipients!</h2>
<p>By moving your loop, you can add many recipients to one e-mail.  However, in doing so, you can no longer use the simple .TO modifier, you need to use the RECIPIENTS collection, and add each e-mail address as their own RECIPIENT.</p>
<p>Happily, it's pretty simple stuff.</p>
<p>So we take the code from above, and we change it a little:</p>
<pre class="code prettyprint lang-vb" style="height: 30em;">' now, this is the meat and potatoes.
 ' this is where we loop through our list of addresses,
 ' adding them to e-mails and sending them.

    Do Until MailList.EOF

           ' This creates the e-mail

        Set MyMail = MyOutlook.CreateItem(olMailItem)

            ' This addresses it
            MyMail.To = MailList("email")

[...]

    'And on to the next one...
    MailList.MoveNext

Loop</pre>
<p>So, we morph this into:</p>
<pre class="code prettyprint lang-vb" style="height: 32em;">
        ' This creates the e-mail
        ' We need to move it BEFORE we start the loop, since
        ' we don't want to make a bunch of e-mails, we just want one.

        Set MyMail = MyOutlook.CreateItem(olMailItem)

         ' now, this is the meat and potatoes.
         ' this is where we loop through our list of addresses,
         ' and we add them to the RECIPIENTS collection

    Do Until MailList.EOF

            ' This adds the address to the list of recipients
            MyMail.Recipients.Add MailList("email")

            'And on to the next one...

    MailList.MoveNext

Loop

			' And now that we've addressed it, we can finish composing the rest of the fields.

            'This gives it a subject

            MyMail.Subject = Subjectline$

               'This gives it the body
            MyMail.Body = MyBodyText

[...]</pre>
<p><a name="changelog"></a></p>
<h2>Changelog</h2>
<p class="tiny">03-28-06: I dropped a link where you can get the DAO libraries</p>
<p class="tiny">02-16-06: Typos stink.  I made a typo in the "many people, one e-mail" message, an equals sign where there shouldn't have been one.  Apologies.  It works now as advertised.</p>
<p class="tiny">02-10-06: I am still amazed at how much traffic this page gets.  Thanks!  I've added a little bit on how to add multiple people to the e-mail, instead of multiples e-mails to one person each...</p>
<p class="tiny">10-24-05: Apparently, I mucked up the personilzation code to the tune of using examples and not the object names we established in the code above it, you can't just cut and paste it.  I've since corrected it, and you should be able to cut-and-paste it now.</p>
<p class="tiny">12-25-03: Merry Christmas!  It seems the attachment code is broken in later versions of Outlook. If you change the position argument to 1 instead of -1, ot seems to work.  I also made an Access 2002 version of the database... dunno why, really... Keep those cards and letters coming... but remember, I can't rewrite this for you or offer too much help... this is meant to help you learn, not just drop it into a project (tho you could!)</p>
<p class="tiny">05-28-02: I'm still flattered at how much e-mail I get from and about this document. I added a bit to explain how to add attachments.</p>
<p class="tiny">11-13-01: I'm flattered at how much e-mail I get from and about this document. I edited the document a little for OfficeXP and added a caveat about newer systems without DAO (Data Access Objects).  Also, added a comment in the code about displaying instead of automaticially sending the e-mail messages.</p>
<p class="tiny">11-28-00: Edited document slightly to re-insert paragraphs about using a text file for the body of the message.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jephens.com/2007/05/13/how-to-send-e-mail-from-ms-access-using-outlook/feed/</wfw:commentRss>
		<slash:comments>182</slash:comments>
		</item>
	</channel>
</rss>

