mimemfc.shtml
来自「mfc资源大全包含MFC编程各个方面的源码」· SHTML 代码 · 共 430 行 · 第 1/2 页
SHTML
430 行
Content-Type: application/octet-stream; file="ATTACHMENT.EXE"
Content-Transfer-Encoding: base64</pre>
<pre>AxfhfujropadladnggnfjgwsaiubvnmkadiuhterqHJSFfuAjkfhrqpeorLAkFn
jNfhgt7Fjd9dfkliodf==</pre>
<pre>--MyBoundaryString--</pre>
<pre>This text is ignored.</pre>
<p>Note that each part of the message conforms to RFC 822,
including the "sub" headers.</p>
<hr>
<h2>The MIME Classes</h2>
<p>At the application level, these classes are simple to use:</p>
<ol>
<li>Create a message object of type CMIMEMessage</li>
<li>Populate it</li>
<li>Call AddMIMEPart() passing the path to a file you want to
attach (one call per file).</li>
<li>Create a CSMTP object and connect to a server</li>
<li>Call the CSMTP object's SendMessage(), giving it the
message object.</li>
<li>Disconnect from the server</li>
</ol>
<p>As is, you can send text messages with one or more reasonably
sized file attachments. But since MIME is constantly evolving,
and you may need to support various character sets, you may need
to extend these classes at some point. So here's how it all
works.</p>
<p><strong>CMIMEMessage</strong></p>
<p>This is where all the action takes place. It is derived from
CMailMessage and works closely with its base class. Conceptually,
CMailMessage represents a message that conforms to RFC 822, and
since MIME merely adds some headers and formats the body,
CMIMEMessage should only do the same. CMailMessage does what it
needs to do to make the message RFC 822-compliant; CMIMEMessage
only tacks on additional information to make the message
MIME-compliant.</p>
<p>CMIMEMessages are themselves made up of distinct parts-- each
with their own content types, parameters and encoding. Instead of
a monolithic class that handles all content types, I decided that
it should know nothing about content types at all. In its
constructor, it registers as many content "agents" as
required. Each agent is identified with a code. Message-parts are
added individually to an internal list along with the code of the
agent that knows how to handle them. When CMIMEMessage needs to
build its body, it asks the appropriate agent to actually
incorporate the part into the body. In this way, whenever I need
to handle a new MIME content type, I create an agent by deriving
from CMIMEContentAgent, and register the agent object in the
constructor of a CMIMEMessage-derived class.</p>
<p>There are two content agents in this package: <strong>CAppOctetStream</strong>
and <strong>CTextPlain</strong>. These classes (both derived from
CMIMEContentAgent) know how to handle the
"application/octet-stream" and "text/plain"
content types, respectively.</p>
<p>The message-parts and agents are kept in sync with a unique
code. Agent objects are given their code when constructed. When
message-parts are added to the message, this same code is used.
The codes are defined as a public enum, <strong>CMIMEMessage::eMIMETypeCode</strong>.
Because the message class controls the codes, it's very easy to
keep things in sync. Note the final item,
"NEXT_FREE_MIME_CODE". When you derive a message class
(and agents) to handle other content types, begin your new codes
with this one. When you register your new agents, give them one
of your new codes.</p>
<p><em>Example</em>:</p>
<p>Say you want to create a message class that handles the
"application/zip" content type.</p>
<p>You'd first derive a CMIMEContentAgent class that does the
useful work. Then you'd derive a message class from CMIMEMessage
and create the appropriate code like this:</p>
<pre>class CEnhancedMIMEMessage::CMIMEMessage
{
public:
enum eMIMETypeCode
{
APP_ZIP = CMIMEMessage::NEXT_FREE_MIME_CODE,
NEXT_FREE_MIME_CODE // Ready to use by 4th-generation class.
};
};</pre>
<p>In the constructor, you'd create the new agent using this code
and register it. You would also use this new code when you add
message-parts.</p>
<p>You can continue this indefinitely-- each sub-class adding the
ability to handle more content types.</p>
<p>The internal class <strong>CMIMETypeManager</strong>, manages
the agents. It's job is to cough up an appropriate agent for a
given content type and to delete the agent objects.</p>
<p><strong>CMailMessage::FormatMessage()</strong> is what gets
the ball rolling. (It is called by CSMTP::SendMessage(), but you
you can call it yourself whenever you want.) There is some
dancing back and forth between base class and derived class
that's not obvious, and you should be aware of it. <strong>CMailMessage::prepare_header()</strong>
is virtual, so FormatMessage() will call the derived class's
version. <em>The first thing the derived class's version does is
call the base class's version</em> so that it can do whatever it
is supposed to do to the header. In this way each class only
worries about its own header lines. (Classes derived from
CMIMEMessage don't need to override prepare_header() because they
<em>are</em> CMIMEMessages, and that class knows how to prepare
its headers.)</p>
<p><strong>CMIMEMessage::AddMIMEPart() </strong>adds
message-parts to the list of parts used to construct the body. It
takes the code of the agent, a <em>suggested</em> encoding type,
the actual content, and a flag argument that indicated whether
the content should be treated as a path or as actual content. The
default parameters supplied are sufficient to attach a file.</p>
<pre>msg.AddMIMEPart( "C:\AUTOEXEC.BAT" ); // Send someone my autoexec file </pre>
<p>It's not only for files, but for any message-part (including
what's normally thought of as the "body"). Indeed, if
you assign the m_sBody member directly (which is perfectly
acceptable), it will get converted into a message-part to be
processed along with the others. Eventually, m_sBody will be a
long string of text incorporating everything in the message.</p>
<h3 align="center">Limitations and Warnings</h3>
<p align="left">CMIMEMessage class doesn't support message
splitting. So if your mail server has a size limit, and doesn't
break apart messages itself, you'll need to derive a class to
handle this. This will involve deriving from CSMTP as well.</p>
<p align="left">CMIMEMessage builds the message body in memory.
If you attach a 100-meg file, it will consume 100 megs of memory,
plus overhead while processing (and I use CStrings extensively). </p>
<p align="left">These two limitations mean that there is an
undefinable size limit for file attachments (undefinable because
it depends on your server and the memory manager used by your
OS).</p>
<p align="left">One of the first enhancements I did was to
override CSMTP::SendMessage() to poll a
CMailMessage::FormatMessage()-like function that returned a
status code to indicate its next course of action. CREATE_NEW
indicated that the CSMTP object should tell the server it's done
with this message and is going to send another one. Also, the
function accepted a buffer and the message was built, one line
per call, into that buffer instead of into m_sHeader and m_sBody.
I can think of 3 other ways to handle this situation, and I'm
sure you can too. Heck, you could even break encapsulation and
just pass a pointer to the CSocket the SMTP object is using. Let
the message object pump its own data to the mail server. </p>
<h3 align="center">Using the Classes in Your Projects</h3>
<p>I know some of you are using the classes from "SMTP MFC
Classes" in your applications. The implementations of those
classes have changed, but the public interfaces are the same. So,
you won't need to redo your source code at all. You will just
need to compile it with the new source code from this package
instead.</p>
<p>Use folder names when you extract the package. You'll find a
folder called \SMTP that contains component files (.OGX) that can
be inserted right into your project.</p>
<p>If you have suggestions, find any bugs, or improve these
classes, feel free to <a href="mailto:clyburnw@enmu.edu">contact
me</a> . In particular, if you develop new content type agents,
I'd love to get my grubby hands on them. </p>
<p><a href="ZapMail.zip">Download</a> the project</p>
<P>
<P>
<HR>
<TABLE BORDER=0 WIDTH="100%" >
<TR>
<TD WIDTH="33%"><FONT SIZE=-1><A HREF="http://www.codeguru.com">Goto HomePage</A></FONT></TD>
<TD WIDTH="33%">
<CENTER><FONT SIZE=-2>© 1998 Zafir Anjum</FONT> </CENTER>
</TD>
<TD WIDTH="34%">
<DIV ALIGN=right><FONT SIZE=-1>Contact me: <A HREF="mailto:zafir@home.com">zafir@home.com</A> </FONT></DIV>
</TD>
</TR>
</TABLE>
</BODY>
</HTML>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?