FINAL suepr merge step : added all modules to this super repos
This commit is contained in:
177
sites/all/modules/contrib/mail/mimemail/CHANGELOG.txt
Normal file
177
sites/all/modules/contrib/mail/mimemail/CHANGELOG.txt
Normal file
@@ -0,0 +1,177 @@
|
||||
Mime Mail 7.x-1.x, xxxx-xx-xx
|
||||
-----------------------
|
||||
- #2020875 by das-peter, Propaganistas: Provide option to set language in Rules actions.
|
||||
- #2045699 by sgabe | Punk_UnDeaD: Boundaries are not unique on Windows.
|
||||
- #1798324 by sgabe, kienan | ShaneOnABike: Return-Path is incorrectly using sender name.
|
||||
- #1790098 by sgabe | edb, Shellingfox: Custom 'from' address comes out as 'Array'.
|
||||
- #1979776 by sgabe | cswolf: Hash mark link gets replaced with site URL.
|
||||
- #1963412 by sgabe | djg_tram: Content-Disposition should default to 'inline'.
|
||||
- #1469828 by sgabe | shadowhitman: Allow to use simple address format only for recipient.
|
||||
- #1947018 by sgabe | bendev: Allow sending plain text messages with Rules.
|
||||
- #962226 by sgabe | rchuber: Allow custom mailkeys for system and Rules action messages.
|
||||
- #1873348 by sgabe | tutumlum: Cannot use tokens in subject and body of HTML email action.
|
||||
- #1439918 by sgabe | Lukas von Blarer: 'Link images only' is not working if the file exists as-is.
|
||||
- #1538004 by sgabe | djg_tram: Change template naming logic to use module as well.
|
||||
- #1719256 by lirantal, sgabe: Handle different files with the same file name.
|
||||
- #1922530 by berliner: Callto links in mail body wrongly replaced.
|
||||
- #1911558 by Simon Georges, JulienD: Remove useless files[] directive from .info files.
|
||||
- #1877928 by sgabe | parasite: Replacing underscore in key is not needed.
|
||||
- #1898140 by MiroslavBanov: Engine variable set to NULL on settings page.
|
||||
- #1780412 by sgabe, kid_icarus: Option to exclude blocked users from a role.
|
||||
- #1814922 by marcusx: Rule sanitizes the $body if populated by a parameter.
|
||||
- #1813348 by sgabe | jdhildeb: Sendmail invoked with empty Return-Path.
|
||||
- #1469022 by sgabe, das-peter | MI: Add 'Reply-to' field to Rules and system actions.
|
||||
- #1773698 by jherencia: Alternatives for mimemail-message.tpl.php do not work.
|
||||
- #1585546 by kotnik, bojanz: Rules actions must be in root module directory.
|
||||
|
||||
Mime Mail 7.x-1.0-alpha2, 2012-08-22
|
||||
-----------------------
|
||||
- #1722188 by sgabe | christian death: Split has been deprecated.
|
||||
- #1643750 by sgabe | MRV: Remove class attributes from the compressed message.
|
||||
- #321026 by sgabe, LUTi | attiks: HTML messages are broken by line breaks.
|
||||
- #1605230 by sgabe | mrbubbs: Extra space in subject caused by wordwrap.
|
||||
- #1662682 by sgabe, itamar: Value may be left unset in requirements check.
|
||||
- #1504782 by rjkuyvenhoven: Update support for Fusion based themes.
|
||||
- #1597896 by sgabe | joewickert: Plus symbol encoded as space in URLs.
|
||||
- #1515660 by sgabe | philsward: Missing upgrade path for Rules actions.
|
||||
- #81707 by sgabe | FredCK, Peters196: Auto-detect appropriate line endings.
|
||||
- #1475664 by sgabe | pumpkinkid: Getting 'Array to string conversion' error.
|
||||
- #1301876 by sean_fremouw: Regex in mimemail_headers() strips allowed characters.
|
||||
- #1432502 by El Bandito: Quotations are not needed to specify an attachment.
|
||||
- #1349728 by jherencia: Possibility to configure the theme that will render the email.
|
||||
- #1391680 by marcdecaluwe: Headers not correctly set.
|
||||
- #1283620 by Cyberwolf: Expose email settings user field to field API.
|
||||
- #1372660 by eueco: Set the proper line ending when calling chunk_split().
|
||||
- #1388786 by tostinni: mimemail_html_body() fails to retrieve file's URI.
|
||||
|
||||
Mime Mail 7.x-1.0-alpha1, 2011-12-18
|
||||
-----------------------
|
||||
- #1372088 by marcus.n3rd.26: Use uri to load mail.css when sending mail.
|
||||
- #1305824 by sgabe: Leave MIME type and use only path to specify an attachment.
|
||||
- #1370422 by awagner: Missing delimiter in file_scan_directory().
|
||||
- #1275734 by gnindl: Scan recursively for mail.css.
|
||||
- #1304332 by sgabe: Token replacement and PHP evaluation in Rules action messages.
|
||||
- #1305830 by sgabe | ibes: Set default filename and mimetype to enforce auto detection.
|
||||
- #1289584 by sgabe | oguerreiro: Check if 'styles' is set.
|
||||
- #1288546 by sgabe | carn1x: Unknown Rules actions.
|
||||
- #1066438 by quicksketch, sgabe, guillaumev, oadaeh: Initial support of attachments.
|
||||
- #1258302 by ralf.strobel: Replace 'arguments' with 'variables' in hook_theme().
|
||||
- #1190144 by Cyberwolf, sgabe: Trim less-than and grater-than chars from Return-Path.
|
||||
- #1140538 by sgabe: Site style sheet isn't included.
|
||||
- #1232266 by InternetDevels.Com: Engine select form element has wrong array key.
|
||||
|
||||
Mime Mail 6.x-1.0, 2011-11-19
|
||||
-----------------------
|
||||
- #1232264 by InternetDevels.Com: Check for not just NULL but empty From address.
|
||||
- #1201154 by guillaumev: Check if attachments is an array and isn't empty.
|
||||
- #1203234 by sgabe | Offlein: Store input format setting for Rules and actions.
|
||||
- #1227242 by sgabe: Remove unnecessary reference signs.
|
||||
- #1076520 by joelstein: Absolute site stylesheets not included.
|
||||
- #1258062 by oadaeh: Don't allow an empty e-mail address with the default engine.
|
||||
- #1270686 by gmania: Don't add Content-Disposition to multipart/alternative parts.
|
||||
- #1260302 by sgabe | prokop1000: Replace encoding detection with UTF-8.
|
||||
- #1270656 by sgabe: From header can be an array which causes errors.
|
||||
- #1301868 by sean_fremouw: Headers overwritten.
|
||||
- #1308628 by sgabe, chriscohen: List function throws notice.
|
||||
- #1301924 by sgabe, ibes: Use array for body in Rules and system actions.
|
||||
- #417462 by plach, Lukas von Blarer, sgabe: Language prefix is not taken into account.
|
||||
- #1181170 by sgabe, Cyberwolf, ibes | windm: Add permission to set user specific settings.
|
||||
- #1309248 by sgabe, gmania: Generate not existing ImageCache images before embedding.
|
||||
- #1304134 by sdague: Add preference to link images.
|
||||
- #1275080 by gmania: Remove the depricated Errors-To header.
|
||||
|
||||
Mime Mail 6.x-1.0-beta2, 2011-06-22
|
||||
----------------------
|
||||
- #1181486 by sgabe: HTML Message not saving in Rules Action form.
|
||||
- #1164870 by itserich: Recipient is not an array anymore.
|
||||
- #1186690 by samhassell: Can't send multiple attachments.
|
||||
|
||||
Mime Mail 6.x-1.0-beta1, 2011-06-04
|
||||
----------------------
|
||||
- #911612 by geneticdrift: Hidden attachments in some email clients.
|
||||
- #1090286 by sgabe: Prepare action messages with drupal_mail() to allow alteration.
|
||||
- #1137358 by sgabe: Tokens don't work in the body of Rules action messages
|
||||
- #1150224 by sgabe: Run filters on the message body of Rules and system actions.
|
||||
- #1090286 by sgabe: Remove process function, fix sending message to a role action.
|
||||
- #1116930 by Pol, sgabe: No text alternative if the CSS is too large.
|
||||
- #808518 by sgabe: Return only the result from drupal_mail_wrapper().
|
||||
- #808518 by claudiu.cristea, sgabe: Split mail preparation from sending.
|
||||
- #1108324 by sgabe: Add input filter to HTML message for system and Rules actions.
|
||||
- #1114536 by rjbrown99: Pass recipient to the template.
|
||||
- #971272 by sgabe: Allow to specify sender's name for Rules action messages.
|
||||
- #1167576 by Pol: Accept plaintext and text parameters for system messages.
|
||||
- #338460 by hopla: Doens't look for mail.css in Zen sub-themes.
|
||||
- #261028 by sgabe, gnosis, mfb, mrfelton, LUTi: SMTP Return-Path Setting.
|
||||
- #1175378 by sgabe, samalone: Include module CSS files in email.
|
||||
|
||||
Mime Mail 6.x-1.0-alpha8, 2011-03-24
|
||||
----------------------
|
||||
- #374615 by joelstein: Set starter default value for plain text user reference.
|
||||
- #1076222 by papasse, Aron Novak: Check the module path on settings submission.
|
||||
- #920904 by fmjrey: Fusion local.css not taken into account.
|
||||
- #443964 by sgabe, pillarsdotnet: Skip style sheets with print media.
|
||||
- #932962 by clydefrog, arvana, sgabe: Allow attachments to be added by contents.
|
||||
- #907716 by isaac.niebeling: Allow non-web-accessible files as attachments.
|
||||
- #758922 by eft, sgabe: Use simple address format for PHP mail() on Windows.
|
||||
|
||||
Mime Mail 6.x-1.0-alpha7, 2011-01-31
|
||||
----------------------
|
||||
- #950456 by stella, sgabe: Check if body encoding can be, and is it detected
|
||||
- #364198 by mfb, sgabe | HS: CSS code in email
|
||||
- #835734 by sgabe | sylvaticus: In some cases CSS optimization causes WSOD
|
||||
- #438058 by AlexisWilke, DanChadwick: Remove line feeds in subject
|
||||
- #979748 by Romka: Missing include in mimemail_mailengine()
|
||||
- #700996 by smk-ka: Custom inline style properties overwritten
|
||||
- #960374 by kim-day: Don't set BCC and CC headers if they are empty
|
||||
- #961536 by clydefrog: Check if sender is empty, not just null
|
||||
- #852698 by sgabe | interestingaftermath: Specify sender's name
|
||||
- #685574 by sgabe, Wim Leers | Michelle: Optional site's css embedding
|
||||
- #758754 by sgabe | mennonot: Add 'Send HTML e-mail' action
|
||||
- #501722 by jpetso, fago, criz, sgabe, aantonop: HTML mail actions for Rules
|
||||
- #729658 by sgabe, Agileware: Allow better integration with Domain Access module
|
||||
- #960726 by sgabe, clydefrog: Send plaintext message if the HTML body is empty
|
||||
|
||||
Mime Mail 6.x-1.0-alpha6, 2010-09-13
|
||||
----------------------
|
||||
- #629038 by Robbert: Attachments dont respect ‘list’ setting
|
||||
- #882960 by sgabe, glynster: CSS Mail Style Sheet Overrides
|
||||
- #319229 by javierreartes, tobiasb, sgabe, crifi: Set $attachments in drupal_wrap_mail()
|
||||
- #903536 by sgabe: Use variable_del() to remove smtp_library()
|
||||
- #456242 by sgabe, kenorb: Use proper operators in if statements with strpos()
|
||||
- #882528 by sgabe | Carsten: Template suggestions based on mailkey
|
||||
- #752838 by sgabe | dsms: Pass $subject to the template
|
||||
- #319384 by sgabe | mariuss: Add $mailkey to body tag as CSS class
|
||||
- #796510 by sgabe | smk-ka: Update CSS Compressor
|
||||
- #614782 by sgabe, Sutharsan: Update README.txt
|
||||
|
||||
Mime Mail 6.x-1.0-alpha5, 2010-08-12
|
||||
----------------------
|
||||
- #850674 by sgabe, AlexisWilke: Prepare function name testing '_prepare'...
|
||||
- #448996 by mfb, hanoii, Sylvain Lecoy: Wrong implementation of hook_mail_alter()
|
||||
- #319229 by sgabe, jm.federico, joostvdl, donquixote, fehin, sunfire-design, mariuss: src='Array' if path to image is broken
|
||||
- #517306 by sgabe, rdosser: Mime Mail Compress mangles absolute URLs in CSS properties
|
||||
- #597448 by sgabe, rmjiv: Unsafe regex pattern in mimemail_extract_files()
|
||||
- #535466 by andreiashu, sgabe: WSOD when using Mime Mail Compress without DOM extension
|
||||
- #513138 by sgabe, peterx: Undefined variables in mimemail.inc
|
||||
- #304476 by sgabe, Thomas_Zahreddin, aaron: PHP Error when Stylesheets don't exist
|
||||
- #710116 by sgabe, neoglez: Wrong implementation/namespace conflict of mimemail_prepare()
|
||||
|
||||
Mime Mail 6.x-1.0-alpha4, 2010-07-10
|
||||
----------------------
|
||||
- #642800 by scronide: Enforce requirement of PHP 5.x for Mime Mail Compress
|
||||
- #740856 by sgabe, Vicbus: Check if the file part is set in the body
|
||||
- #567594 by hanoii: $mailkey is not properly set in drupal_mail_wrapper()
|
||||
- #768794 by sgabe, danyg: Check if the name is empty when the address is an object
|
||||
- #700996 by sgabe, -Mania-: Custom inline style properties overwritten when using CSS Compressor
|
||||
- #729334 by plach: Flawed CSS to XPath conversion for class selectors in Mime Mail CSS Compressor
|
||||
- #456260 by sgabe, kenorb, kscheirer, mitchmac: WSOD: smtp_library variable is not removed when Mime Mail has been disabled
|
||||
- #698794 by sgabe, mobilis: Attachment Content-Type-fix
|
||||
- #629038 by jackinloadup, sgabe: Attachments don't respect list setting
|
||||
|
||||
Mime Mail 6.x-1.0-alpha3, 2010-06-16
|
||||
----------------------
|
||||
- #358439 by folkertdv: Images are only in the first message
|
||||
- #448670 by sgabe, gregarios, moritzz: Spaces and Line Breaks are removed from CSS definitions
|
||||
- #372710 by LUTi, sgabe, perarnet: HTML emails are text-only in Hotmail
|
||||
- #583920 by Sutharsan, sgabe: Can't override mimemail.tpl.php
|
||||
- #127876 by sgabe, Sutharsan, jerdavis: Plain text with/without attachment
|
339
sites/all/modules/contrib/mail/mimemail/LICENSE.txt
Normal file
339
sites/all/modules/contrib/mail/mimemail/LICENSE.txt
Normal file
@@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
128
sites/all/modules/contrib/mail/mimemail/README.txt
Normal file
128
sites/all/modules/contrib/mail/mimemail/README.txt
Normal file
@@ -0,0 +1,128 @@
|
||||
|
||||
-- SUMMARY --
|
||||
|
||||
This is a Mime Mail component module (for use by other modules).
|
||||
* It permits users to recieve HTML email and can be used by other modules. The mail
|
||||
functionality accepts an HTML message body, mime-endcodes it and sends it.
|
||||
* If the HTML has embedded graphics, these graphics are MIME-encoded and included
|
||||
as a message attachment.
|
||||
* Adopts your site's style by automatically including your theme's stylesheet files in a
|
||||
themeable HTML message format
|
||||
* If the recipient's preference is available and they prefer plaintext, the HTML will be
|
||||
converted to plain text and sent as-is. Otherwise, the email will be sent in themeable
|
||||
HTML with a plaintext alternative.
|
||||
|
||||
For a full description of the module, visit the project page:
|
||||
http://drupal.org/project/mimemail
|
||||
|
||||
To submit bug reports and feature suggestions, or to track changes:
|
||||
http://drupal.org/project/issues/mimemail
|
||||
|
||||
|
||||
-- REQUIREMENTS --
|
||||
|
||||
Mail System module - http://drupal.org/project/mailsystem
|
||||
|
||||
|
||||
-- INSTALLATION --
|
||||
|
||||
Hopefully, you know the drill by now :)
|
||||
1. Download the module and extract the files.
|
||||
2. Upload the entire mimemail folder into your Drupal sites/all/modules/
|
||||
or sites/my.site.folder/modules/ directory if you are running a multi-site
|
||||
installation of Drupal and you want this module to be specific to a
|
||||
particular site in your installation.
|
||||
3. Enable the Mime Mail module by navigating to:
|
||||
Administration > Modules
|
||||
4. Adjust settings by navigating to:
|
||||
Administration > Configuration > Mime Mail
|
||||
|
||||
|
||||
-- USAGE --
|
||||
|
||||
This module may be required by other modules, but in favor of the recently
|
||||
added system actions and Rules integration, it can be useful by itself too.
|
||||
|
||||
Once installed, any module can send MIME-encoded messages by specifing
|
||||
MimeMailSystem as the responsible mail system for a particular message
|
||||
or all mail sent by one module.
|
||||
|
||||
This can be done through the web by visiting admin/config/system/mailsystem
|
||||
or in a program as follows:
|
||||
|
||||
mailsystem_set(array(
|
||||
'{$module}_{$key}' => 'MimeMailSystem', // Just messages with $key sent by $module.
|
||||
'{$module}' => 'MimeMailSystem', // All messages sent by $module.
|
||||
));
|
||||
|
||||
You can use the following optional parameters to build the e-mail:
|
||||
'plain':
|
||||
Boolean, whether to send messages in plaintext-only (optional, default is FALSE).
|
||||
'plaintext':
|
||||
Plaintext portion of a multipart e-mail (optional).
|
||||
'attachments':
|
||||
Array of arrays with the path or content, name and MIME type of the file (optional).
|
||||
'headers':
|
||||
A keyed array with headers (optional).
|
||||
|
||||
You can set these in $params either before calling drupal_mail() or in hook_mail()
|
||||
and of course hook_mail_alter().
|
||||
|
||||
Normally, Mime Mail uses email addresses in the form of "name" <address@host.com>,
|
||||
but PHP running on Windows servers requires extra SMTP handling to use this format.
|
||||
If you are running your site on a Windows server and don't have an SMTP solution such
|
||||
as the SMTP module installed, you may need to set the 'Use the simple format of
|
||||
user@example.com for all email addresses' option on the configuration settings page.
|
||||
|
||||
This module creates a user preference for receiving plaintext-only messages.
|
||||
This preference will be honored by all messages if the format is not explicitly set
|
||||
and the user has access to edit this preference (allowed by default).
|
||||
|
||||
Email messages are formatted using the mimemail-message.tpl.php template.
|
||||
This includes a CSS style sheet and uses an HTML version of the text.
|
||||
The included CSS is either:
|
||||
the mail.css file found anywhere in your theme folder or
|
||||
the combined CSS style sheets of your theme if enabled.
|
||||
|
||||
To create a custom mail template copy the mimemail-message.tpl.php file from
|
||||
the mimemail/theme directory into your default theme's folder. Both general and
|
||||
by-mailkey theming can be performed:
|
||||
mimemail-message--[module]--[key].tpl.php (for messages with a specific module and key)
|
||||
mimemail-message--[module].tpl.php (for messages with a specific module)
|
||||
mimemail-message--[key].tpl.php (for messages with a specific key)
|
||||
mimemail-message.tpl.php (for all messages)
|
||||
|
||||
Messages can be rendered using different themes. You can choose the following
|
||||
settings to render the e-mail:
|
||||
'current': Theme currently used by the user who runs drupal_mail().
|
||||
'default': Default theme, obtained via variable theme_default.
|
||||
'domain': Theme obtained via Domain Theme module.
|
||||
or any other active theme.
|
||||
|
||||
Images with absolute URL will be available as remote content. To embed images
|
||||
into emails you have to use a relative URL or an internal path.
|
||||
For example:
|
||||
instead of http://www.mysite.com/sites/default/files/mypicture.jpg
|
||||
use /home/www/public_html/drupal/sites/default/files/mypicture.jpg
|
||||
or /sites/default/files/mypicture.jpg
|
||||
|
||||
Since some email clients (namely Outlook 2007 and GMail) is tend to only regard
|
||||
inline CSS, you can use the Compressor to convert CSS styles into inline style
|
||||
attributes. It transmogrifies the HTML source by parsing the CSS and inserting the
|
||||
CSS definitions into tags within the HTML based on the CSS selectors. To use the
|
||||
Compressor, just enable it.
|
||||
|
||||
|
||||
-- CREDITS --
|
||||
|
||||
MAINTAINER: Allie Micka < allie at pajunas dot com >
|
||||
|
||||
* Allie Micka
|
||||
Mime enhancements and HTML mail code
|
||||
|
||||
* Gerhard Killesreiter
|
||||
Original mail and mime code
|
||||
|
||||
* Robert Castelo
|
||||
HTML to Text and other functionality
|
||||
|
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Configuration settings page for sending MIME-encoded emails.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Configuration form.
|
||||
*/
|
||||
function mimemail_admin_settings() {
|
||||
// Check for the existence of a mail.css file in the default theme folder.
|
||||
$theme = variable_get('theme_default', NULL);
|
||||
$mailstyle = drupal_get_path('theme', $theme) . '/mail.css';
|
||||
// Disable site style sheets including option if found.
|
||||
if (is_file($mailstyle)) {
|
||||
variable_set('mimemail_sitestyle', 0);
|
||||
$disable_sitestyle = TRUE;
|
||||
}
|
||||
else {
|
||||
$disable_sitestyle = FALSE;
|
||||
}
|
||||
|
||||
$form = array();
|
||||
$form['mimemail']['mimemail_name'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Sender name'),
|
||||
'#default_value' => variable_get('mimemail_name', variable_get('site_name', 'Drupal')),
|
||||
'#size' => 60,
|
||||
'#maxlength' => 128,
|
||||
'#description' => t('The name that all site emails will be from when using default engine.'),
|
||||
);
|
||||
$form['mimemail']['mimemail_mail'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Sender e-mail address'),
|
||||
'#default_value' => variable_get('mimemail_mail', variable_get('site_mail', ini_get('sendmail_from'))),
|
||||
'#size' => 60,
|
||||
'#maxlength' => 128,
|
||||
'#description' => t('The email address that all site e-mails will be from when using default engine.'),
|
||||
);
|
||||
$form['mimemail']['mimemail_simple_address'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Use simple address format'),
|
||||
'#default_value' => variable_get('mimemail_simple_address', FALSE),
|
||||
'#description' => t('Use the simple format of user@example.com for all recipient email addresses.'),
|
||||
);
|
||||
$form['mimemail']['mimemail_sitestyle'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Include site style sheets'),
|
||||
'#default_value' => variable_get('mimemail_sitestyle', TRUE),
|
||||
'#description' => t('Gather all style sheets when no mail.css found in the default theme directory.'),
|
||||
'#disabled' => $disable_sitestyle,
|
||||
);
|
||||
$form['mimemail']['mimemail_textonly'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Send plain text email only'),
|
||||
'#default_value' => variable_get('mimemail_textonly', FALSE),
|
||||
'#description' => t('This option disables the use of email messages with graphics and styles. All messages will be converted to plain text.'),
|
||||
);
|
||||
$form['mimemail']['mimemail_linkonly'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Link images only'),
|
||||
'#default_value' => variable_get('mimemail_linkonly', 0),
|
||||
'#description' => t('This option disables the embedding of images. All image will be available as external content. This can make email messages much smaller.'),
|
||||
);
|
||||
if (module_exists('mimemail_compress')) {
|
||||
$form['mimemail']['mimemail_preserve_class'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Preserve class attributes'),
|
||||
'#default_value' => variable_get('mimemail_preserve_class', 0),
|
||||
'#description' => t('This option disables the removing of class attributes from the message source. Useful for debugging the style of the message.'),
|
||||
);
|
||||
}
|
||||
|
||||
// Get a list of all formats.
|
||||
$formats = filter_formats();
|
||||
foreach ($formats as $format) {
|
||||
$format_options[$format->format] = $format->name;
|
||||
}
|
||||
$form['mimemail']['mimemail_format'] = array(
|
||||
'#type' => 'select',
|
||||
'#title' => t('E-mail format'),
|
||||
'#options' => $format_options,
|
||||
'#default_value' => variable_get('mimemail_format', filter_fallback_format()),
|
||||
'#access' => count($formats) > 1,
|
||||
'#attributes' => array('class' => array('filter-list')),
|
||||
);
|
||||
|
||||
$form['mimemail']['advanced'] = array(
|
||||
'#type' => 'fieldset',
|
||||
'#title' => t('Advanced settings'),
|
||||
'#collapsible' => TRUE,
|
||||
'#collapsed' => TRUE,
|
||||
);
|
||||
$form['mimemail']['advanced']['mimemail_incoming'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Process incoming messages posted to this site'),
|
||||
'#default_value' => variable_get('mimemail_incoming', FALSE),
|
||||
'#description' => t('This is an advanced setting that should not be enabled unless you know what you are doing.'),
|
||||
);
|
||||
$form['mimemail']['advanced']['mimemail_key'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Message validation string'),
|
||||
'#default_value' => variable_get('mimemail_key', md5(rand())),
|
||||
'#required' => TRUE,
|
||||
'#description' => t('This string will be used to validate incoming messages. It can be anything, but must be used on both sides of the transfer.'),
|
||||
);
|
||||
|
||||
// Get the available mail engines.
|
||||
$engines = mimemail_get_engines();
|
||||
foreach ($engines as $module => $engine) {
|
||||
$engine_options[$module] = $engine['name'] . ': ' . $engine['description'];
|
||||
}
|
||||
// Hide the settings if only 1 engine is available.
|
||||
if (count($engines) == 1) {
|
||||
reset($engines);
|
||||
variable_set('mimemail_engine', key($engines));
|
||||
$form['mimemail']['mimemail_engine'] = array(
|
||||
'#type' => 'hidden',
|
||||
'#value' => variable_get('mimemail_engine', 'mimemail'),
|
||||
);
|
||||
}
|
||||
else {
|
||||
$form['mimemail']['mimemail_engine'] = array(
|
||||
'#type' => 'select',
|
||||
'#title' => t('E-mail engine'),
|
||||
'#default_value' => variable_get('mimemail_engine', 'mimemail'),
|
||||
'#options' => $engine_options,
|
||||
'#description' => t('Choose an engine for sending mails from your site.'),
|
||||
);
|
||||
}
|
||||
|
||||
if (variable_get('mimemail_engine', 'mail')) {
|
||||
$settings = module_invoke(variable_get('mimemail_engine', 'mimemail'), 'mailengine', 'settings');
|
||||
if ($settings) {
|
||||
$form['mimemail']['engine_settings'] = array(
|
||||
'#type' => 'fieldset',
|
||||
'#title' => t('Engine specific settings'),
|
||||
);
|
||||
foreach ($settings as $name => $value) {
|
||||
$form['mimemail']['engine_settings'][$name] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
drupal_set_message(t('Please choose a mail engine.'), 'error');
|
||||
}
|
||||
|
||||
return system_settings_form($form);
|
||||
}
|
@@ -0,0 +1,203 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Functions that handle inbound messages to mimemail.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Receive messages POSTed from an external source.
|
||||
*
|
||||
* This function enables messages to be sent via POST or some other RFC822
|
||||
* source input (e.g. directly from a mail server).
|
||||
*
|
||||
* @return
|
||||
* The POSTed message.
|
||||
*/
|
||||
function mimemail_post() {
|
||||
$message = $_POST['message'];
|
||||
$token = $_POST['token'];
|
||||
$hash = md5(variable_get('mimemail_key', '**') . $message);
|
||||
|
||||
if ($hash != $token) {
|
||||
watchdog('access denied', 'Authentication error for POST e-mail', WATCHDOG_WARNING);
|
||||
return drupal_access_denied();
|
||||
}
|
||||
return mimemail_incoming($message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an externally received message.
|
||||
*
|
||||
* @param $message
|
||||
* The message to parse.
|
||||
*/
|
||||
function mimemail_incoming($message) {
|
||||
$mail = mimemail_parse($message);
|
||||
|
||||
foreach (module_implements('mimemail_incoming_alter') as $module) {
|
||||
call_user_func_array($module . '_mimemail_incoming_alter', $mail);
|
||||
}
|
||||
|
||||
module_invoke_all('mimemail_incoming', $mail);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a message into its parts.
|
||||
*
|
||||
* @param string $message
|
||||
* The message to parse.
|
||||
*
|
||||
* @return array
|
||||
* The parts of the message.
|
||||
*/
|
||||
function mimemail_parse($message) {
|
||||
// Provides a "headers", "content-type" and "body" element.
|
||||
$mail = mimemail_parse_headers($message);
|
||||
|
||||
// Get an address-only version of "From" (useful for user_load() and such).
|
||||
$mail['from'] = preg_replace('/.*\b([a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4})\b.*/i', '\1', drupal_strtolower($mail['headers']['From']));
|
||||
|
||||
// Get a subject line, which may be cleaned up/modified later.
|
||||
$mail['subject'] = $mail['headers']['Subject'];
|
||||
|
||||
// Make an array to hold any non-content attachments.
|
||||
$mail['attachments'] = array();
|
||||
|
||||
// We're dealing with a multi-part message.
|
||||
$mail['parts'] = mimemail_parse_boundary($mail);
|
||||
|
||||
foreach ($mail['parts'] as $i => $part_body) {
|
||||
$part = mimemail_parse_headers($part_body);
|
||||
$sub_parts = mimemail_parse_boundary($part);
|
||||
|
||||
// Content is encoded in a multipart/alternative section.
|
||||
if (count($sub_parts) > 1) {
|
||||
foreach ($sub_parts as $j => $sub_part_body) {
|
||||
$sub_part = mimemail_parse_headers($sub_part_body);
|
||||
if ($sub_part['content-type'] == 'text/plain') {
|
||||
$mail['text'] = mimemail_parse_content($sub_part);
|
||||
}
|
||||
if ($sub_part['content-type'] == 'text/html') {
|
||||
$mail['html'] = mimemail_parse_content($sub_part);
|
||||
}
|
||||
else {
|
||||
$mail['attachments'][] = mimemail_parse_attachment($sub_part);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (($part['content-type'] == 'text/plain') && !isset($mail['text'])) {
|
||||
$mail['text'] = mimemail_parse_content($part);
|
||||
}
|
||||
elseif (($part['content-type'] == 'text/html') && !isset($mail['html'])) {
|
||||
$mail['html'] = mimemail_parse_content($part);
|
||||
}
|
||||
else {
|
||||
$mail['attachments'][] = mimemail_parse_attachment($part);
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure our text and html parts are accounted for.
|
||||
if (isset($mail['html']) && !isset($mail['text'])) {
|
||||
$mail['text'] = preg_replace('|<style.*</style>|mis', '', $mail['html']);
|
||||
$mail['text'] = drupal_html_to_text($mail['text']);
|
||||
}
|
||||
elseif (isset($mail['text']) && !isset($mail['html'])) {
|
||||
$mail['html'] = check_markup($mail['text'], variable_get('mimemail_format', filter_fallback_format()));
|
||||
}
|
||||
|
||||
// Last ditch attempt - use the body as-is.
|
||||
if (!isset($mail['text'])) {
|
||||
$mail['text'] = mimemail_parse_content($mail);
|
||||
$mail['html'] = check_markup($mail['text'], variable_get('mimemail_format', filter_fallback_format()));
|
||||
}
|
||||
|
||||
return $mail;
|
||||
}
|
||||
|
||||
/**
|
||||
* Split a multi-part message using MIME boundaries.
|
||||
*/
|
||||
function mimemail_parse_boundary($part) {
|
||||
$m = array();
|
||||
if (preg_match('/.*boundary="?([^";]+)"?.*/', $part['headers']['Content-Type'], $m)) {
|
||||
$boundary = "\n--" . $m[1];
|
||||
$body = str_replace("$boundary--", '', $part['body']);
|
||||
return array_slice(explode($boundary, $body), 1);
|
||||
}
|
||||
return array($part['body']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Split a message (or message part) into its headers and body section.
|
||||
*/
|
||||
function mimemail_parse_headers($message) {
|
||||
// Split out body and headers.
|
||||
if (preg_match("/^(.*?)\r?\n\r?\n(.*)/s", $message, $match)) {
|
||||
list($hdr, $body) = array($match[1], $match[2]);
|
||||
}
|
||||
|
||||
// Un-fold the headers.
|
||||
$hdr = preg_replace(array("/\r/", "/\n(\t| )+/"), array('', ' '), $hdr);
|
||||
|
||||
$headers = array();
|
||||
foreach (explode("\n", trim($hdr)) as $row) {
|
||||
$split = strpos($row, ':');
|
||||
$name = trim(drupal_substr($row, 0, $split));
|
||||
$val = trim(drupal_substr($row, $split+1));
|
||||
$headers[$name] = $val;
|
||||
}
|
||||
|
||||
$type = (preg_replace('/\s*([^;]+).*/', '\1', $headers['Content-Type']));
|
||||
|
||||
return array('headers' => $headers, 'body' => $body, 'content-type' => $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a decoded MIME part in UTF-8.
|
||||
*/
|
||||
function mimemail_parse_content($part) {
|
||||
$content = $part['body'];
|
||||
|
||||
// Decode this part.
|
||||
if ($encoding = drupal_strtolower($part['headers']['Content-Transfer-Encoding'])) {
|
||||
switch ($encoding) {
|
||||
case 'base64':
|
||||
$content = base64_decode($content);
|
||||
break;
|
||||
case 'quoted-printable':
|
||||
$content = quoted_printable_decode($content);
|
||||
break;
|
||||
// 7bit is the RFC default.
|
||||
case '7bit':
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to convert character set to UTF-8.
|
||||
if (preg_match('/.*charset="?([^";]+)"?.*/', $part['headers']['Content-Type'], $m)) {
|
||||
$content = drupal_convert_to_utf8($content, $m[1]);
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a MIME part into a file array.
|
||||
*/
|
||||
function mimemail_parse_attachment($part) {
|
||||
$m = array();
|
||||
if (preg_match('/.*filename="?([^";])"?.*/', $part['headers']['Content-Disposition'], $m)) {
|
||||
$name = $m[1];
|
||||
}
|
||||
elseif (preg_match('/.*name="?([^";])"?.*/', $part['headers']['Content-Type'], $m)) {
|
||||
$name = $m[1];
|
||||
}
|
||||
|
||||
return array(
|
||||
'filename' => $name,
|
||||
'filemime' => $part['content-type'],
|
||||
'content' => mimemail_parse_content($part),
|
||||
);
|
||||
}
|
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Mime Mail implementations of MailSystemInterface.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modify the Drupal mail system to send HTML emails.
|
||||
*/
|
||||
class MimeMailSystem implements MailSystemInterface {
|
||||
/**
|
||||
* Concatenate and wrap the e-mail body for HTML mails.
|
||||
*
|
||||
* @param array $message
|
||||
* A message array, as described in hook_mail_alter() with optional
|
||||
* parameters described in mimemail_prepare_message().
|
||||
*
|
||||
* @return array
|
||||
* The formatted $message.
|
||||
*/
|
||||
public function format(array $message) {
|
||||
if (is_array($message['body'])) {
|
||||
$message['body'] = implode("\n\n", $message['body']);
|
||||
}
|
||||
|
||||
if (preg_match('/plain/', $message['headers']['Content-Type'])) {
|
||||
$message['body'] = check_markup($message['body'], variable_get('mimemail_format', filter_fallback_format()));
|
||||
}
|
||||
|
||||
$engine = variable_get('mimemail_engine', 'mimemail');
|
||||
$mailengine = $engine . '_mailengine';
|
||||
$engine_prepare_message = $engine . '_prepare_message';
|
||||
|
||||
if (function_exists($engine_prepare_message)) {
|
||||
$message = $engine_prepare_message($message);
|
||||
}
|
||||
else {
|
||||
$message = mimemail_prepare_message($message);
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
/**
|
||||
* Send an HTML e-mail message, using Drupal variables and default settings.
|
||||
*
|
||||
* @param array $message
|
||||
* A message array, as described in hook_mail_alter() with optional
|
||||
* parameters described in mimemail_prepare_message().
|
||||
*
|
||||
* @return boolean
|
||||
* TRUE if the mail was successfully accepted, otherwise FALSE.
|
||||
*/
|
||||
public function mail(array $message) {
|
||||
$engine = variable_get('mimemail_engine', 'mimemail');
|
||||
$mailengine = $engine . '_mailengine';
|
||||
|
||||
if (!$engine || !function_exists($mailengine)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return $mailengine('send', $message);
|
||||
}
|
||||
}
|
554
sites/all/modules/contrib/mail/mimemail/mimemail.inc
Normal file
554
sites/all/modules/contrib/mail/mimemail/mimemail.inc
Normal file
@@ -0,0 +1,554 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Common mail functions for sending e-mail. Originally written by Gerhard.
|
||||
*
|
||||
* Allie Micka <allie at pajunas dot com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Attempts to RFC822-compliant headers for the mail message or its MIME parts.
|
||||
*
|
||||
* @todo Could use some enhancement and stress testing.
|
||||
*
|
||||
* @param array $headers
|
||||
* An array of headers.
|
||||
*
|
||||
* @return string
|
||||
* A string containing the headers.
|
||||
*/
|
||||
function mimemail_rfc_headers($headers) {
|
||||
$header = '';
|
||||
$crlf = variable_get('mimemail_crlf', MAIL_LINE_ENDINGS);
|
||||
foreach ($headers as $key => $value) {
|
||||
$key = trim($key);
|
||||
// Collapse spaces and get rid of newline characters.
|
||||
$value = preg_replace('/(\s+|\n|\r|^\s|\s$)/', ' ', $value);
|
||||
// Fold headers if they're too long.
|
||||
if (drupal_strlen($value) > 60) {
|
||||
// If there's a semicolon, use that to separate.
|
||||
if (count($array = preg_split('/;\s*/', $value)) > 1) {
|
||||
$value = trim(join(";$crlf ", $array));
|
||||
}
|
||||
else {
|
||||
$value = wordwrap($value, 50, "$crlf ", FALSE);
|
||||
}
|
||||
}
|
||||
$header .= "$key: $value$crlf";
|
||||
}
|
||||
return trim($header);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives useful defaults for standard email headers.
|
||||
*
|
||||
* @param array $headers
|
||||
* Message headers.
|
||||
* @param string $from
|
||||
* The address of the sender.
|
||||
*
|
||||
* @return array
|
||||
* Overwrited headers.
|
||||
*/
|
||||
function mimemail_headers($headers, $from = NULL) {
|
||||
$default_from = variable_get('site_mail', ini_get('sendmail_from'));
|
||||
|
||||
// Overwrite standard headers.
|
||||
if ($from) {
|
||||
if (!isset($headers['From']) || $headers['From'] == $default_from) {
|
||||
$headers['From'] = $from;
|
||||
}
|
||||
if (!isset($headers['Sender']) || $headers['Sender'] == $default_from) {
|
||||
$headers['Sender'] = $from;
|
||||
}
|
||||
// This may not work. The MTA may rewrite the Return-Path.
|
||||
if (!isset($headers['Return-Path']) || $headers['Return-Path'] == $default_from) {
|
||||
preg_match('/[a-z\d\-\.\+_]+@(?:[a-z\d\-]+\.)+[a-z\d]{2,4}/i', $from, $matches);
|
||||
$headers['Return-Path'] = "<$matches[0]>";
|
||||
}
|
||||
}
|
||||
|
||||
// Convert From header if it is an array.
|
||||
if (is_array($headers['From'])) {
|
||||
$headers['From'] = mimemail_address($headers['From']);
|
||||
}
|
||||
|
||||
// Run all headers through mime_header_encode() to convert non-ascii
|
||||
// characters to an rfc compliant string, similar to drupal_mail().
|
||||
foreach ($headers as $key => $value) {
|
||||
$headers[$key] = mime_header_encode($value);
|
||||
}
|
||||
|
||||
return $headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts links to local images from HTML documents.
|
||||
*
|
||||
* @param string $html
|
||||
* A string containing the HTML source of the message.
|
||||
*
|
||||
* @return array
|
||||
* An array containing the document body and the extracted files like the following.
|
||||
* array(
|
||||
* array(
|
||||
* 'name' => document name
|
||||
* 'content' => html text, local image urls replaced by Content-IDs,
|
||||
* 'Content-Type' => 'text/html; charset=utf-8')
|
||||
* array(
|
||||
* 'name' => file name,
|
||||
* 'file' => reference to local file,
|
||||
* 'Content-ID' => generated Content-ID,
|
||||
* 'Content-Type' => derived using mime_content_type if available, educated guess otherwise
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
function mimemail_extract_files($html) {
|
||||
$pattern = '/(<link[^>]+href=[\'"]?|<object[^>]+codebase=[\'"]?|@import |[\s]src=[\'"]?)([^\'>"]+)([\'"]?)/mis';
|
||||
$content = preg_replace_callback($pattern, '_mimemail_replace_files', $html);
|
||||
|
||||
$encoding = '8Bit';
|
||||
$body = explode("\n", $content);
|
||||
foreach ($body as $line) {
|
||||
if (drupal_strlen($line) > 998) {
|
||||
$encoding = 'base64';
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($encoding == 'base64') {
|
||||
$content = rtrim(chunk_split(base64_encode($content)));
|
||||
}
|
||||
|
||||
$document = array(array(
|
||||
'Content-Type' => "text/html; charset=utf-8",
|
||||
'Content-Transfer-Encoding' => $encoding,
|
||||
'content' => $content,
|
||||
));
|
||||
|
||||
$files = _mimemail_file();
|
||||
|
||||
return array_merge($document, $files);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback function for preg_replace_callback().
|
||||
*/
|
||||
function _mimemail_replace_files($matches) {
|
||||
return stripslashes($matches[1]) . _mimemail_file($matches[2]) . stripslashes($matches[3]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to extract local files.
|
||||
*
|
||||
* @param string $url
|
||||
* (optional) The URI or the absolute URL to the file.
|
||||
* @param string $content
|
||||
* (optional) The actual file content.
|
||||
* @param string $name
|
||||
* (optional) The file name.
|
||||
* @param string $type
|
||||
* (optional) The file type.
|
||||
* @param string $disposition
|
||||
* (optional) The content disposition. Defaults to inline.
|
||||
*
|
||||
* @return
|
||||
* The Content-ID and/or an array of the files on success or the URL on failure.
|
||||
*/
|
||||
function _mimemail_file($url = NULL, $content = NULL, $name = '', $type = '', $disposition = 'inline') {
|
||||
static $files = array();
|
||||
static $ids = array();
|
||||
|
||||
if ($url) {
|
||||
$image = preg_match('!\.(png|gif|jpg|jpeg)$!i', $url);
|
||||
$linkonly = variable_get('mimemail_linkonly', 0);
|
||||
// The file exists on the server as-is. Allows for non-web-accessible files.
|
||||
if (@is_file($url) && $image && !$linkonly) {
|
||||
$file = $url;
|
||||
}
|
||||
else {
|
||||
$url = _mimemail_url($url, 'TRUE');
|
||||
// The $url is absolute, we're done here.
|
||||
$scheme = file_uri_scheme($url);
|
||||
if ($scheme == 'http' || $scheme == 'https' || preg_match('!mailto:!', $url)) {
|
||||
return $url;
|
||||
}
|
||||
// The $url is a non-local URI that needs to be converted to a URL.
|
||||
else {
|
||||
$file = (drupal_realpath($url)) ? drupal_realpath($url) : file_create_url($url);
|
||||
}
|
||||
}
|
||||
}
|
||||
// We have the actual content.
|
||||
elseif ($content) {
|
||||
$file = $content;
|
||||
}
|
||||
|
||||
if (isset($file) && (@is_file($file) || $content)) {
|
||||
|
||||
if (!$name) {
|
||||
$name = (@is_file($file)) ? basename($file) : 'attachment.dat';
|
||||
}
|
||||
if (!$type) {
|
||||
$type = ($name) ? file_get_mimetype($name) : file_get_mimetype($file);
|
||||
}
|
||||
|
||||
$id = md5($file) .'@'. $_SERVER['HTTP_HOST'];
|
||||
|
||||
// Prevent duplicate items.
|
||||
if (isset($ids[$id])) {
|
||||
return 'cid:'. $ids[$id];
|
||||
}
|
||||
|
||||
$new_file = array(
|
||||
'name' => $name,
|
||||
'file' => $file,
|
||||
'Content-ID' => $id,
|
||||
'Content-Disposition' => $disposition,
|
||||
'Content-Type' => $type,
|
||||
);
|
||||
|
||||
$files[] = $new_file;
|
||||
$ids[$id] = $id;
|
||||
|
||||
return 'cid:' . $id;
|
||||
}
|
||||
// The $file does not exist and no $content, return the $url if possible.
|
||||
elseif ($url) {
|
||||
return $url;
|
||||
}
|
||||
|
||||
$ret = $files;
|
||||
$files = array();
|
||||
$ids = array();
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a multipart body.
|
||||
*
|
||||
* @param array $parts
|
||||
* An associative array containing the parts to be included:
|
||||
* - name: A string containing the name of the attachment.
|
||||
* - content: A string containing textual content.
|
||||
* - file: A string containing file content.
|
||||
* - Content-Type: A string containing the content type of either file or content. Mandatory
|
||||
* for content, optional for file. If not present, it will be derived from file the file if
|
||||
* mime_content_type is available. If not, application/octet-stream is used.
|
||||
* - Content-Disposition: (optional) A string containing the disposition. Defaults to inline.
|
||||
* - Content-Transfer-Encoding: (optional) Base64 is assumed for files, 8bit for other content.
|
||||
* - Content-ID: (optional) for in-mail references to attachements.
|
||||
* Name is mandatory, one of content and file is required, they are mutually exclusive.
|
||||
* @param string $content_type
|
||||
* (optional) A string containing the content-type for the combined message. Defaults to
|
||||
* multipart/mixed.
|
||||
*
|
||||
* @return array
|
||||
* An associative array containing the following elements:
|
||||
* - body: A string containing the MIME-encoded multipart body of a mail.
|
||||
* - headers: An array that includes some headers for the mail to be sent.
|
||||
*/
|
||||
function mimemail_multipart_body($parts, $content_type = 'multipart/mixed; charset=utf-8', $sub_part = FALSE) {
|
||||
$boundary = md5(uniqid($_SERVER['REQUEST_TIME'], TRUE));
|
||||
$body = '';
|
||||
$headers = array(
|
||||
'Content-Type' => "$content_type; boundary=\"$boundary\"",
|
||||
);
|
||||
if (!$sub_part) {
|
||||
$headers['MIME-Version'] = '1.0';
|
||||
$body = "This is a multi-part message in MIME format.\n";
|
||||
}
|
||||
|
||||
foreach ($parts as $part) {
|
||||
$part_headers = array();
|
||||
|
||||
if (isset($part['Content-ID'])) {
|
||||
$part_headers['Content-ID'] = '<' . $part['Content-ID'] . '>';
|
||||
}
|
||||
|
||||
if (isset($part['Content-Type'])) {
|
||||
$part_headers['Content-Type'] = $part['Content-Type'];
|
||||
}
|
||||
|
||||
if (isset($part['Content-Disposition'])) {
|
||||
$part_headers['Content-Disposition'] = $part['Content-Disposition'];
|
||||
}
|
||||
elseif (strpos($part['Content-Type'], 'multipart/alternative') === FALSE) {
|
||||
$part_headers['Content-Disposition'] = 'inline';
|
||||
}
|
||||
|
||||
if (isset($part['Content-Transfer-Encoding'])) {
|
||||
$part_headers['Content-Transfer-Encoding'] = $part['Content-Transfer-Encoding'];
|
||||
}
|
||||
|
||||
// Mail content provided as a string.
|
||||
if (isset($part['content']) && $part['content']) {
|
||||
if (!isset($part['Content-Transfer-Encoding'])) {
|
||||
$part_headers['Content-Transfer-Encoding'] = '8bit';
|
||||
}
|
||||
$part_body = $part['content'];
|
||||
if (isset($part['name'])) {
|
||||
$part_headers['Content-Type'] .= '; name="' . $part['name'] . '"';
|
||||
$part_headers['Content-Disposition'] .= '; filename="' . $part['name'] . '"';
|
||||
}
|
||||
|
||||
// Mail content references in a filename.
|
||||
}
|
||||
else {
|
||||
if (!isset($part['Content-Transfer-Encoding'])) {
|
||||
$part_headers['Content-Transfer-Encoding'] = 'base64';
|
||||
}
|
||||
|
||||
if (!isset($part['Content-Type'])) {
|
||||
$part['Content-Type'] = file_get_mimetype($part['file']);
|
||||
}
|
||||
|
||||
if (isset($part['name'])) {
|
||||
$part_headers['Content-Type'] .= '; name="' . $part['name'] . '"';
|
||||
$part_headers['Content-Disposition'] .= '; filename="' . $part['name'] . '"';
|
||||
}
|
||||
|
||||
if (isset($part['file'])) {
|
||||
$file = (is_file($part['file'])) ? file_get_contents($part['file']) : $part['file'];
|
||||
$part_body = chunk_split(base64_encode($file), 76, variable_get('mimemail_crlf', "\n"));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
$body .= "\n--$boundary\n";
|
||||
$body .= mimemail_rfc_headers($part_headers) . "\n\n";
|
||||
$body .= isset($part_body) ? $part_body : '';
|
||||
}
|
||||
$body .= "\n--$boundary--\n";
|
||||
|
||||
return array('headers' => $headers, 'body' => $body);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for preg_replace_callback().
|
||||
*/
|
||||
function _mimemail_expand_links($matches) {
|
||||
return $matches[1] . _mimemail_url($matches[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a multipart message body with a text alternative for some HTML text.
|
||||
*
|
||||
* @param string $body
|
||||
* The HTML message body.
|
||||
* @param string $subject
|
||||
* The message subject.
|
||||
* @param boolean $plain
|
||||
* (optional) Whether the recipient prefers plaintext-only messages. Defaults to FALSE.
|
||||
* @param string $plaintext
|
||||
* (optional) The plaintext message body.
|
||||
* @param array $attachments
|
||||
* (optional) The files to be attached to the message.
|
||||
*
|
||||
* @return array
|
||||
* An associative array containing the following elements:
|
||||
* - body: A string containing the MIME-encoded multipart body of a mail.
|
||||
* - headers: An array that includes some headers for the mail to be sent.
|
||||
*
|
||||
* The first mime part is a multipart/alternative containing mime-encoded sub-parts for
|
||||
* HTML and plaintext. Each subsequent part is the required image or attachment.
|
||||
*/
|
||||
function mimemail_html_body($body, $subject, $plain = FALSE, $plaintext = NULL, $attachments = array()) {
|
||||
if (empty($plaintext)) {
|
||||
// @todo Remove once filter_xss() can handle direct descendant selectors in inline CSS.
|
||||
// @see http://drupal.org/node/1116930
|
||||
// @see http://drupal.org/node/370903
|
||||
// Pull out the message body.
|
||||
preg_match('|<body.*?</body>|mis', $body, $matches);
|
||||
$plaintext = drupal_html_to_text($matches[0]);
|
||||
}
|
||||
if ($plain) {
|
||||
// Plain mail without attachment.
|
||||
if (empty($attachments)) {
|
||||
$content_type = 'text/plain';
|
||||
return array(
|
||||
'body' => $plaintext,
|
||||
'headers' => array('Content-Type' => 'text/plain; charset=utf-8'),
|
||||
);
|
||||
}
|
||||
// Plain mail with attachement.
|
||||
else {
|
||||
$content_type = 'multipart/mixed';
|
||||
$parts = array(array(
|
||||
'content' => $plaintext,
|
||||
'Content-Type' => 'text/plain; charset=utf-8',
|
||||
));
|
||||
}
|
||||
}
|
||||
else {
|
||||
$content_type = 'multipart/mixed';
|
||||
|
||||
$plaintext_part = array('Content-Type' => 'text/plain; charset=utf-8', 'content' => $plaintext);
|
||||
|
||||
// Expand all local links.
|
||||
$pattern = '/(<a[^>]+href=")([^"]*)/mi';
|
||||
$body = preg_replace_callback($pattern, '_mimemail_expand_links', $body);
|
||||
|
||||
$mime_parts = mimemail_extract_files($body);
|
||||
|
||||
$content = array($plaintext_part, array_shift($mime_parts));
|
||||
$content = mimemail_multipart_body($content, 'multipart/alternative', TRUE);
|
||||
$parts = array(array('Content-Type' => $content['headers']['Content-Type'], 'content' => $content['body']));
|
||||
|
||||
if ($mime_parts) {
|
||||
$parts = array_merge($parts, $mime_parts);
|
||||
$content = mimemail_multipart_body($parts, 'multipart/related; type="multipart/alternative"', TRUE);
|
||||
$parts = array(array('Content-Type' => $content['headers']['Content-Type'], 'content' => $content['body']));
|
||||
}
|
||||
}
|
||||
|
||||
if (is_array($attachments) && !empty($attachments)) {
|
||||
foreach ($attachments as $a) {
|
||||
$a = (object) $a;
|
||||
$path = isset($a->uri) ? $a->uri : (isset($a->filepath) ? $a->filepath : NULL);
|
||||
$content = isset($a->filecontent) ? $a->filecontent : NULL;
|
||||
$name = isset($a->filename) ? $a->filename : NULL;
|
||||
$type = isset($a->filemime) ? $a->filemime : NULL;
|
||||
_mimemail_file($path, $content, $name, $type, 'attachment');
|
||||
$parts = array_merge($parts, _mimemail_file());
|
||||
}
|
||||
}
|
||||
|
||||
return mimemail_multipart_body($parts, $content_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to format URLs.
|
||||
*
|
||||
* @param string $url
|
||||
* The file path.
|
||||
*
|
||||
* @return string
|
||||
* A processed URL.
|
||||
*/
|
||||
function _mimemail_url($url, $embed_file = NULL) {
|
||||
global $base_url;
|
||||
$url = urldecode($url);
|
||||
|
||||
// If the URL is absolute or a mailto, return it as-is.
|
||||
if (strpos($url, '://') !== FALSE || preg_match('!(mailto|callto|tel)\:!', $url)) {
|
||||
$url = str_replace(' ', '%20', $url);
|
||||
return $url;
|
||||
}
|
||||
// If the image embedding is disabled, return the absolute URL for the image.
|
||||
elseif (variable_get('mimemail_linkonly', 0) && preg_match('!\.(png|gif|jpg|jpeg)$!i', $url)) {
|
||||
$url = $base_url . $url;
|
||||
$url = str_replace(' ', '%20', $url);
|
||||
return $url;
|
||||
}
|
||||
|
||||
$url = preg_replace('!^' . base_path() . '!', '', $url, 1);
|
||||
|
||||
// If we're processing to embed the file, we're done here so return.
|
||||
if ($embed_file) {
|
||||
return $url;
|
||||
}
|
||||
|
||||
if (!preg_match('!^\?q=*!', $url)) {
|
||||
$strip_clean = TRUE;
|
||||
}
|
||||
|
||||
$url = str_replace('?q=', '', $url);
|
||||
@list($url, $fragment) = explode('#', $url, 2);
|
||||
@list($path, $query) = explode('?', $url, 2);
|
||||
|
||||
// If we're dealing with an intra-document reference, return it.
|
||||
if (empty($path)) {
|
||||
return '#' . $fragment;
|
||||
}
|
||||
|
||||
// Get a list of enabled languages.
|
||||
$languages = language_list('enabled');
|
||||
$languages = $languages[1];
|
||||
|
||||
// Default language settings.
|
||||
$prefix = '';
|
||||
$language = language_default();
|
||||
|
||||
// Check for language prefix.
|
||||
$args = explode('/', $path);
|
||||
foreach ($languages as $lang) {
|
||||
if ($args[0] == $lang->prefix) {
|
||||
$prefix = array_shift($args);
|
||||
$language = $lang;
|
||||
$path = implode('/', $args);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$options = array(
|
||||
'query' => ($query) ? drupal_get_query_array($query) : array(),
|
||||
'fragment' => $fragment,
|
||||
'absolute' => TRUE,
|
||||
'language' => $language,
|
||||
'prefix' => $prefix,
|
||||
);
|
||||
|
||||
$url = url($path, $options);
|
||||
|
||||
// If url() added a ?q= where there should not be one, remove it.
|
||||
if (isset($strip_clean) && $strip_clean) {
|
||||
$url = preg_replace('!\?q=!', '', $url);
|
||||
}
|
||||
|
||||
$url = str_replace('+', '%2B', $url);
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats an address string.
|
||||
*
|
||||
* @todo Could use some enhancement and stress testing.
|
||||
*
|
||||
* @param mixed $address
|
||||
* A user object, a text email address or an array containing name, mail.
|
||||
* @param boolean $simplify
|
||||
* Determines if the address needs to be simplified. Defaults to FALSE.
|
||||
*
|
||||
* @return string
|
||||
* A formatted address string or FALSE.
|
||||
*/
|
||||
function mimemail_address($address, $simplify = FALSE) {
|
||||
if (is_array($address)) {
|
||||
// It's an array containing 'mail' and/or 'name'.
|
||||
if (isset($address['mail'])) {
|
||||
$output = '';
|
||||
if (empty($address['name']) || $simplify) {
|
||||
return $address['mail'];
|
||||
}
|
||||
else {
|
||||
return '"' . addslashes(mime_header_encode($address['name'])) . '" <' . $address['mail'] . '>';
|
||||
}
|
||||
}
|
||||
// It's an array of address items.
|
||||
$addresses = array();
|
||||
foreach ($address as $a) {
|
||||
$addresses[] = mimemail_address($a);
|
||||
}
|
||||
return $addresses;
|
||||
}
|
||||
|
||||
// It's a user object.
|
||||
if (is_object($address) && isset($address->mail)) {
|
||||
if (empty($address->name) || $simplify) {
|
||||
return $address->mail;
|
||||
}
|
||||
else {
|
||||
return '"' . addslashes(mime_header_encode($address->name)) . '" <' . $address->mail . '>';
|
||||
}
|
||||
}
|
||||
|
||||
// It's formatted or unformatted string.
|
||||
// @todo: shouldn't assume it's valid - should try to re-parse
|
||||
if (is_string($address)) {
|
||||
return $address;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
21
sites/all/modules/contrib/mail/mimemail/mimemail.info
Normal file
21
sites/all/modules/contrib/mail/mimemail/mimemail.info
Normal file
@@ -0,0 +1,21 @@
|
||||
name = Mime Mail
|
||||
description = Send MIME-encoded emails with embedded images and attachments.
|
||||
dependencies[] = mailsystem
|
||||
package = Mail
|
||||
core = 7.x
|
||||
|
||||
configure = admin/config/system/mimemail
|
||||
|
||||
files[] = includes/mimemail.mail.inc
|
||||
|
||||
; Tests
|
||||
files[] = tests/mimemail.test
|
||||
files[] = tests/mimemail_rules.test
|
||||
files[] = tests/mimemail_compress.test
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-09-06
|
||||
version = "7.x-1.0-alpha2+30-dev"
|
||||
core = "7.x"
|
||||
project = "mimemail"
|
||||
datestamp = "1378431585"
|
||||
|
111
sites/all/modules/contrib/mail/mimemail/mimemail.install
Normal file
111
sites/all/modules/contrib/mail/mimemail/mimemail.install
Normal file
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Install, update and uninstall functions for Mime Mail module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_install().
|
||||
*/
|
||||
function mimemail_install() {
|
||||
user_role_grant_permissions(DRUPAL_AUTHENTICATED_RID, array('edit mimemail user settings'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_enable().
|
||||
*/
|
||||
function mimemail_enable() {
|
||||
module_load_include('module', 'mailsystem');
|
||||
mailsystem_set(
|
||||
array(
|
||||
mailsystem_default_id() => 'MimeMailSystem',
|
||||
'mimemail' => 'MimeMailSystem',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_disable().
|
||||
*/
|
||||
function mimemail_disable() {
|
||||
mailsystem_clear(array('mimemail' => 'MimeMailSystem'));
|
||||
variable_set('mimemail_alter', FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_uninstall().
|
||||
*/
|
||||
function mimemail_uninstall() {
|
||||
$variables = array(
|
||||
'mimemail_alter',
|
||||
'mimemail_crlf',
|
||||
'mimemail_engine',
|
||||
'mimemail_incoming',
|
||||
'mimemail_key',
|
||||
'mimemail_textonly',
|
||||
'mimemail_sitestyle',
|
||||
'mimemail_name',
|
||||
'mimemail_mail',
|
||||
'mimemail_format',
|
||||
'mimemail_simple_address',
|
||||
'mimemail_linkonly',
|
||||
'mimemail_preserve_class'
|
||||
);
|
||||
foreach ($variables as $variable) {
|
||||
variable_del($variable);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_requirements().
|
||||
*
|
||||
* Ensures that the newly-required Mail System module is available, or else
|
||||
* disables the Mime Mail module and returns an informative error message.
|
||||
*/
|
||||
function mimemail_requirements($phase) {
|
||||
if ($phase === 'install' || module_exists('mailsystem')) {
|
||||
return array();
|
||||
}
|
||||
$args = array(
|
||||
'!mailsystem' => url('http://drupal.org/project/mailsystem'),
|
||||
'%mailsystem' => 'Mail System',
|
||||
'!mimemail' => url('http://drupal.org/project/mimemail'),
|
||||
'%mimemail' => 'Mime Mail',
|
||||
);
|
||||
if ( module_enable(array('mailsystem'))
|
||||
&& module_load_include('module', 'mailsystem')
|
||||
) {
|
||||
drupal_set_message(
|
||||
t('The %mailsystem module has been enabled because the %mimemail module now requires it.', $args)
|
||||
);
|
||||
return array();
|
||||
}
|
||||
return array(
|
||||
'mimemail_mailsystem' => array(
|
||||
'title' => t('%mailsystem module', $args),
|
||||
'value' => t('Not installed'),
|
||||
'description' => t(
|
||||
'The <a href="!smtp">%mimemail</a> module dependencies have changed. Please download and install the required <a href="!mailsystem">%mailsystem</a> module, then re-enable the <a href="!mimemail">%mimemail</a> module.', $args
|
||||
),
|
||||
'severity' => REQUIREMENT_ERROR,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check installation requirements.
|
||||
*/
|
||||
function mimemail_update_7000() {
|
||||
if ($requirements = mimemail_requirements('runtime')) {
|
||||
throw new DrupalUpdateException($requirements['mimemail_mailsystem']['description']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes useless variables.
|
||||
*/
|
||||
function mimemail_update_7001() {
|
||||
variable_del('mimemail_theme');
|
||||
}
|
||||
|
384
sites/all/modules/contrib/mail/mimemail/mimemail.module
Normal file
384
sites/all/modules/contrib/mail/mimemail/mimemail.module
Normal file
@@ -0,0 +1,384 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Component module for sending Mime-encoded emails.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_menu().
|
||||
*/
|
||||
function mimemail_menu() {
|
||||
$path = drupal_get_path('module', 'mimemail') . '/includes';
|
||||
// Configuration links.
|
||||
$items['admin/config/system/mimemail'] = array(
|
||||
'title' => 'Mime Mail',
|
||||
'description' => 'Manage mime mail system settings.',
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('mimemail_admin_settings'),
|
||||
'access arguments' => array('administer site configuration'),
|
||||
'file' => 'mimemail.admin.inc',
|
||||
'file path' => $path,
|
||||
);
|
||||
$items['mimemail'] = array(
|
||||
'page callback' => 'mimemail_post',
|
||||
'access callback' => 'mimemail_incoming_access',
|
||||
'type' => MENU_CALLBACK,
|
||||
'file' => 'mimemail.incoming.inc',
|
||||
'file path' => $path,
|
||||
);
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_permission().
|
||||
*/
|
||||
function mimemail_permission() {
|
||||
return array(
|
||||
'edit mimemail user settings' => array(
|
||||
'title' => t('Edit Mime Mail user settings'),
|
||||
'description' => t('Edit user specific settings for Mime Mail.'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Access callback to process incoming messages.
|
||||
*/
|
||||
function mimemail_incoming_access() {
|
||||
return variable_get('mimemail_incoming', FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_field_extra_fields().
|
||||
*/
|
||||
function mimemail_field_extra_fields() {
|
||||
$extra['user']['user'] = array(
|
||||
'form' => array(
|
||||
'mimemail' => array(
|
||||
'label' => t('Email'),
|
||||
'description' => t('Mime Mail module settings form elements.'),
|
||||
'weight' => 0,
|
||||
),
|
||||
),
|
||||
'display' => array(
|
||||
'mimemail' => array(
|
||||
'label' => t('Email'),
|
||||
'description' => t('Mime Mail module settings form elements.'),
|
||||
'weight' => 0,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return $extra;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_user_view().
|
||||
*/
|
||||
function mimemail_user_view($account, $view_mode, $langcode) {
|
||||
$account->content['mimemail'] = array(
|
||||
'#type' => 'user_profile_category',
|
||||
'#title' => t('Email'),
|
||||
);
|
||||
|
||||
$account->content['mimemail']['textonly'] = array(
|
||||
'#type' => 'user_profile_item',
|
||||
'#title' => t('Plaintext email only'),
|
||||
'#markup' => empty($account->data['mimemail_textonly']) ? t('No') : t('Yes'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_form_FORM_ID_alter().
|
||||
*
|
||||
* Adds the Mime Mail settings on the user settings page.
|
||||
*/
|
||||
function mimemail_form_user_profile_form_alter(&$form, &$form_state) {
|
||||
if ($form['#user_category'] == 'account') {
|
||||
$account = $form['#user'];
|
||||
$form['mimemail'] = array(
|
||||
'#type' => 'fieldset',
|
||||
'#title' => t('Email settings'),
|
||||
'#weight' => 5,
|
||||
'#collapsible' => TRUE,
|
||||
'#access' => user_access('edit mimemail user settings'),
|
||||
);
|
||||
$form['mimemail']['mimemail_textonly'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Plaintext email only'),
|
||||
'#default_value' => !empty($account->data['mimemail_textonly']) ? $account->data['mimemail_textonly'] : FALSE,
|
||||
'#description' => t('Check this option if you do not wish to receive email messages with graphics and styles.'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_user_presave().
|
||||
*/
|
||||
function mimemail_user_presave(&$edit, $account, $category) {
|
||||
$edit['data']['mimemail_textonly'] = isset($edit['mimemail_textonly']) ? $edit['mimemail_textonly'] : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_theme().
|
||||
*/
|
||||
function mimemail_theme() {
|
||||
module_load_include('inc', 'mimemail', 'theme/mimemail.theme');
|
||||
return mimemail_theme_theme();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_mail().
|
||||
*/
|
||||
function mimemail_mail($key, &$message, $params) {
|
||||
$context = $params['context'];
|
||||
|
||||
// Prepare the array of the attachments.
|
||||
$attachments = array();
|
||||
$attachments_string = trim($params['attachments']);
|
||||
if (!empty($attachments_string)) {
|
||||
$attachment_lines = array_filter(explode("\n", trim($attachments_string)));
|
||||
foreach ($attachment_lines as $filepath) {
|
||||
$attachments[] = array(
|
||||
'filepath' => trim($filepath),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// We handle different address headers if set.
|
||||
$address_headers = array(
|
||||
'cc' => 'Cc',
|
||||
'bcc' => 'Bcc',
|
||||
'reply-to' => 'Reply-to',
|
||||
);
|
||||
foreach ($address_headers as $param_key => $address_header) {
|
||||
$params[$param_key] = empty($params[$param_key]) ? array() : explode(',', $params[$param_key]);
|
||||
if (!empty($params[$param_key])) {
|
||||
foreach ($params[$param_key] as $key => $address) {
|
||||
$params[$param_key][$key] = token_replace($address, $context);
|
||||
}
|
||||
$message['headers'][$address_header] = implode(',', $params[$param_key]);
|
||||
}
|
||||
}
|
||||
|
||||
$message['to'] = token_replace($message['to'], $context);
|
||||
$message['subject'] = token_replace($context['subject'], $context);
|
||||
$message['body'][] = token_replace($context['body'], $context);
|
||||
$message['params']['plaintext'] = token_replace($params['plaintext'], $context);
|
||||
$message['params']['attachments'] = $attachments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retreives a list of all available mailer engines.
|
||||
*
|
||||
* @return array
|
||||
* Mailer engine names.
|
||||
*/
|
||||
function mimemail_get_engines() {
|
||||
$engines = array();
|
||||
foreach (module_implements('mailengine') as $module) {
|
||||
$engines[$module] = module_invoke($module, 'mailengine', 'list');
|
||||
}
|
||||
return $engines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_mailengine().
|
||||
*
|
||||
* @param string $op
|
||||
* The operation to perform on the message.
|
||||
* @param array $message
|
||||
* The message to perform the operation on.
|
||||
*
|
||||
* @return boolean
|
||||
* Returns TRUE if the operation was successful or FALSE if it was not.
|
||||
*/
|
||||
function mimemail_mailengine($op, $message = array()) {
|
||||
module_load_include('inc', 'mimemail');
|
||||
|
||||
switch ($op) {
|
||||
case 'list':
|
||||
$engine = array(
|
||||
'name' => t('Mime Mail'),
|
||||
'description' => t("Default mailing engine."),
|
||||
);
|
||||
return $engine;
|
||||
case 'settings':
|
||||
// Not implemented.
|
||||
break;
|
||||
case 'multiple':
|
||||
case 'single':
|
||||
case 'send':
|
||||
// Default values.
|
||||
$default = array(
|
||||
'to' => '',
|
||||
'subject' => '',
|
||||
'body' => '',
|
||||
'from' => '',
|
||||
'headers' => ''
|
||||
);
|
||||
$message = array_merge($default, $message);
|
||||
|
||||
// If 'Return-Path' isn't already set in php.ini, we pass it separately
|
||||
// as an additional parameter instead of in the header.
|
||||
// However, if PHP's 'safe_mode' is on, this is not allowed.
|
||||
if (isset($message['headers']['Return-Path']) && !ini_get('safe_mode')) {
|
||||
$return_path_set = strpos(ini_get('sendmail_path'), ' -f');
|
||||
if (!$return_path_set) {
|
||||
$return_path = trim($message['headers']['Return-Path'], '<>');
|
||||
unset($message['headers']['Return-Path']);
|
||||
}
|
||||
}
|
||||
|
||||
$crlf = variable_get('mimemail_crlf', MAIL_LINE_ENDINGS);
|
||||
|
||||
$recipients = (!is_array($message['to'])) ? array($message['to']) : $message['to'];
|
||||
$subject = mime_header_encode($message['subject']);
|
||||
$body = preg_replace('@\r?\n@', $crlf, $message['body']);
|
||||
$headers = mimemail_rfc_headers($message['headers']);
|
||||
|
||||
$result = TRUE;
|
||||
foreach ($recipients as $to) {
|
||||
if (isset($return_path) && !empty($return_path)) {
|
||||
if (isset($_SERVER['WINDIR']) || strpos($_SERVER['SERVER_SOFTWARE'], 'Win32') !== FALSE) {
|
||||
// On Windows, PHP will use the value of sendmail_from for the
|
||||
// Return-Path header.
|
||||
$old_from = ini_get('sendmail_from');
|
||||
ini_set('sendmail_from', $return_path);
|
||||
$result = @mail($to, $subject, $body, $headers) && $result;
|
||||
ini_set('sendmail_from', $old_from);
|
||||
}
|
||||
else {
|
||||
// On most non-Windows systems, the "-f" option to the sendmail command
|
||||
// is used to set the Return-Path.
|
||||
$result = @mail($to, $subject, $body, $headers, '-f' . $return_path) && $result;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// The optional $additional_parameters argument to mail() is not allowed
|
||||
// if safe_mode is enabled. Passing any value throws a PHP warning and
|
||||
// makes mail() return FALSE.
|
||||
$result = @mail($to, $subject, $body, $headers) && $result;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the message for sending.
|
||||
*
|
||||
* @param array $message
|
||||
* An array containing the message data. The optional parameters are:
|
||||
* - plain: Whether to send the message as plaintext only or HTML. If evaluates to TRUE,
|
||||
* then the message will be sent as plaintext.
|
||||
* - plaintext: Optional plaintext portion of a multipart email.
|
||||
* - attachments: An array of arrays which describe one or more attachments.
|
||||
* Existing files can be added by path, dinamically-generated files
|
||||
* can be added by content. The internal array contains the following elements:
|
||||
* - filepath: Relative Drupal path to an existing file (filecontent is NULL).
|
||||
* - filecontent: The actual content of the file (filepath is NULL).
|
||||
* - filename: The filename of the file.
|
||||
* - filemime: The MIME type of the file.
|
||||
* The array of arrays looks something like this:
|
||||
* Array
|
||||
* (
|
||||
* [0] => Array
|
||||
* (
|
||||
* [filepath] => '/sites/default/files/attachment.txt'
|
||||
* [filecontent] => 'My attachment.'
|
||||
* [filename] => 'attachment.txt'
|
||||
* [filemime] => 'text/plain'
|
||||
* )
|
||||
* )
|
||||
*
|
||||
* @return array
|
||||
* All details of the message.
|
||||
*/
|
||||
function mimemail_prepare_message($message) {
|
||||
module_load_include('inc', 'mimemail');
|
||||
|
||||
$module = $message['module'];
|
||||
$key = $message['key'];
|
||||
$to = $message['to'];
|
||||
$from = $message['from'];
|
||||
$subject = $message['subject'];
|
||||
$body = $message['body'];
|
||||
|
||||
$headers = isset($message['params']['headers']) ? $message['params']['headers'] : array();
|
||||
$plain = isset($message['params']['plain']) ? $message['params']['plain'] : NULL;
|
||||
$plaintext = isset($message['params']['plaintext']) ? $message['params']['plaintext'] : NULL;
|
||||
$attachments = isset($message['params']['attachments']) ? $message['params']['attachments'] : array();
|
||||
|
||||
$site_name = variable_get('site_name', 'Drupal');
|
||||
$site_mail = variable_get('site_mail', ini_get('sendmail_from'));
|
||||
$simple_address = variable_get('mimemail_simple_address', 0);
|
||||
|
||||
// Override site mails default sender when using default engine.
|
||||
if ((empty($from) || $from == $site_mail)
|
||||
&& variable_get('mimemail_engine', 'mimemail') == 'mimemail') {
|
||||
$mimemail_name = variable_get('mimemail_name', $site_name);
|
||||
$mimemail_mail = variable_get('mimemail_mail', $site_mail);
|
||||
$from = array(
|
||||
'name' => !empty($mimemail_name) ? $mimemail_name : $site_name,
|
||||
'mail' => !empty($mimemail_mail) ? $mimemail_mail : $site_mail,
|
||||
);
|
||||
}
|
||||
|
||||
// Body is empty, this is a plaintext message.
|
||||
if (empty($body)) {
|
||||
$plain = TRUE;
|
||||
}
|
||||
// Try to determine recipient's text mail preference.
|
||||
elseif (is_null($plain)) {
|
||||
if (is_object($to) && isset($to->data['mimemail_textonly'])) {
|
||||
$plain = $to->data['mimemail_textonly'];
|
||||
}
|
||||
elseif (is_string($to) && valid_email_address($to)) {
|
||||
if (is_object($account = user_load_by_mail($to)) && isset($account->data['mimemail_textonly'])) {
|
||||
$plain = $account->data['mimemail_textonly'];
|
||||
// Might as well pass the user object to the address function.
|
||||
$to = $account;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$subject = str_replace(array(" \n", "\n"), '', trim(drupal_html_to_text($subject)));
|
||||
|
||||
$hook = array(
|
||||
'mimemail_message__' . $key,
|
||||
'mimemail_message__' . $module .'__'. $key,
|
||||
);
|
||||
|
||||
$variables = array(
|
||||
'module' => $module,
|
||||
'key' => $key,
|
||||
'recipient' => $to,
|
||||
'subject' => $subject,
|
||||
'body' => $body
|
||||
);
|
||||
|
||||
$body = theme($hook, $variables);
|
||||
|
||||
foreach (module_implements('mail_post_process') as $module) {
|
||||
$function = $module . '_mail_post_process';
|
||||
$function($body, $key);
|
||||
}
|
||||
|
||||
$plain = $plain || variable_get('mimemail_textonly', 0);
|
||||
$from = mimemail_address($from);
|
||||
$mail = mimemail_html_body($body, $subject, $plain, $plaintext, $attachments);
|
||||
$headers = array_merge($message['headers'], $headers, $mail['headers']);
|
||||
|
||||
$message['to'] = mimemail_address($to, $simple_address);
|
||||
$message['from'] = $from;
|
||||
$message['subject'] = $subject;
|
||||
$message['body'] = $mail['body'];
|
||||
$message['headers'] = mimemail_headers($headers, $from);
|
||||
|
||||
return $message;
|
||||
}
|
353
sites/all/modules/contrib/mail/mimemail/mimemail.rules.inc
Normal file
353
sites/all/modules/contrib/mail/mimemail/mimemail.rules.inc
Normal file
@@ -0,0 +1,353 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Rules actions for sending Mime-encoded emails.
|
||||
*
|
||||
* @addtogroup rules
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_rules_action_info().
|
||||
*/
|
||||
function mimemail_rules_action_info() {
|
||||
return array(
|
||||
'mimemail' => array(
|
||||
'label' => t('Send HTML e-mail'),
|
||||
'group' => t('System'),
|
||||
'parameter' => array(
|
||||
'key' => array(
|
||||
'type' => 'text',
|
||||
'label' => t('Key'),
|
||||
'description' => t('A key to identify the e-mail sent.'),
|
||||
),
|
||||
'to' => array(
|
||||
'type' => 'text',
|
||||
'label' => t('To'),
|
||||
'description' => t("The mail's recipient address. The formatting of this string must comply with RFC 2822."),
|
||||
),
|
||||
'cc' => array(
|
||||
'type' => 'text',
|
||||
'label' => t('CC Recipient'),
|
||||
'description' => t("The mail's carbon copy address. You may separate multiple addresses with comma."),
|
||||
'optional' => TRUE,
|
||||
),
|
||||
'bcc' => array(
|
||||
'type' => 'text',
|
||||
'label' => t('BCC Recipient'),
|
||||
'description' => t("The mail's blind carbon copy address. You may separate multiple addresses with comma."),
|
||||
'optional' => TRUE,
|
||||
),
|
||||
'from_name' => array(
|
||||
'type' => 'text',
|
||||
'label' => t('Sender name'),
|
||||
'description' => t("The sender's name. Leave it empty to use the site-wide configured name."),
|
||||
'optional' => TRUE,
|
||||
),
|
||||
'from_mail' => array(
|
||||
'type' => 'text',
|
||||
'label' => t('Sender e-mail address'),
|
||||
'description' => t("The sender's address. Leave it empty to use the site-wide configured address."),
|
||||
'optional' => TRUE,
|
||||
),
|
||||
'reply_to' => array(
|
||||
'type' => 'text',
|
||||
'label' => t('Reply e-mail address'),
|
||||
'description' => t("The address to reply to. Leave it empty to use the sender's address."),
|
||||
'optional' => TRUE,
|
||||
),
|
||||
'subject' => array(
|
||||
'type' => 'text',
|
||||
'label' => t('Subject'),
|
||||
'description' => t("The mail's subject."),
|
||||
'translatable' => TRUE,
|
||||
),
|
||||
'body' => array(
|
||||
'type' => 'text',
|
||||
'label' => t('Body'),
|
||||
'description' => t("The mail's message HTML body."),
|
||||
'sanitize' => TRUE,
|
||||
'optional' => TRUE,
|
||||
'translatable' => TRUE,
|
||||
),
|
||||
'plaintext' => array(
|
||||
'type' => 'text',
|
||||
'label' => t('Plain text body'),
|
||||
'description' => t("The mail's message plaintext body."),
|
||||
'optional' => TRUE,
|
||||
'translatable' => TRUE,
|
||||
),
|
||||
'attachments' => array(
|
||||
'type' => 'text',
|
||||
'label' => t('Attachments'),
|
||||
'description' => t("The mail's attachments, one file per line e.g. \"files/images/mypic.png\" without quotes."),
|
||||
'optional' => TRUE,
|
||||
),
|
||||
'language' => array(
|
||||
'type' => 'token',
|
||||
'label' => t('Language'),
|
||||
'description' => t('If specified, the language used for getting the mail message and subject.'),
|
||||
'options list' => 'entity_metadata_language_list',
|
||||
'optional' => TRUE,
|
||||
'default value' => LANGUAGE_NONE,
|
||||
'default mode' => 'selector',
|
||||
),
|
||||
),
|
||||
'base' => 'rules_action_mimemail',
|
||||
'access callback' => 'rules_system_integration_access',
|
||||
),
|
||||
'mimemail_to_users_of_role' => array(
|
||||
'label' => t('Send HTML mail to all users of a role'),
|
||||
'group' => t('System'),
|
||||
'parameter' => array(
|
||||
'key' => array(
|
||||
'type' => 'text',
|
||||
'label' => t('Key'),
|
||||
'description' => t('A key to identify the e-mail sent.'),
|
||||
),
|
||||
'roles' => array(
|
||||
'type' => 'list<integer>',
|
||||
'label' => t('Roles'),
|
||||
'options list' => 'entity_metadata_user_roles',
|
||||
'description' => t('Select the roles whose users should receive the mail.'),
|
||||
),
|
||||
'active' => array(
|
||||
'type' => 'boolean',
|
||||
'label' =>('Send to active users'),
|
||||
'description' => t('Send mail only to active users.'),
|
||||
),
|
||||
'from_name' => array(
|
||||
'type' => 'text',
|
||||
'label' => t('Sender name'),
|
||||
'description' => t("The sender's name. Leave it empty to use the site-wide configured name."),
|
||||
'optional' => TRUE,
|
||||
),
|
||||
'from_mail' => array(
|
||||
'type' => 'text',
|
||||
'label' => t('Sender e-mail address'),
|
||||
'description' => t("The sender's address. Leave it empty to use the site-wide configured address."),
|
||||
'optional' => TRUE,
|
||||
),
|
||||
'subject' => array(
|
||||
'type' => 'text',
|
||||
'label' => t('Subject'),
|
||||
'description' => t("The mail's subject."),
|
||||
'translatable' => TRUE,
|
||||
),
|
||||
'body' => array(
|
||||
'type' => 'text',
|
||||
'label' => t('Body'),
|
||||
'description' => t("The mail's message HTML body."),
|
||||
'optional' => TRUE,
|
||||
'translatable' => TRUE,
|
||||
),
|
||||
'plaintext' => array(
|
||||
'type' => 'text',
|
||||
'label' => t('Plaintext body'),
|
||||
'description' => t("The mail's message plaintext body."),
|
||||
'optional' => TRUE,
|
||||
'translatable' => TRUE,
|
||||
),
|
||||
'attachments' => array(
|
||||
'type' => 'text',
|
||||
'label' => t('Attachments'),
|
||||
'description' => t("The mail's attachments, one file per line e.g. \"files/images/mypic.png\" without quotes."),
|
||||
'optional' => TRUE,
|
||||
),
|
||||
'language_user' => array(
|
||||
'type' => 'boolean',
|
||||
'label' => t("Send mail in each recipient's language"),
|
||||
'description' => t("If checked, the mail message and subject will be sent in each user's preferred language. <strong>You can safely leave the language selector below empty if this option is selected.</strong>"),
|
||||
),
|
||||
'language' => array(
|
||||
'type' => 'token',
|
||||
'label' => t('Fixed language'),
|
||||
'description' => t('If specified, the fixed language used for getting the mail message and subject.'),
|
||||
'options list' => 'entity_metadata_language_list',
|
||||
'optional' => TRUE,
|
||||
'default value' => LANGUAGE_NONE,
|
||||
'default mode' => 'selector',
|
||||
),
|
||||
),
|
||||
'base' => 'rules_action_mimemail_to_users_of_role',
|
||||
'access callback' => 'rules_system_integration_access',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_rules_action_base_upgrade_map_name().
|
||||
*/
|
||||
function mimemail_rules_action_mail_upgrade_map_name($element) {
|
||||
return 'mimemail';
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_rules_action_base_upgrade_map_name().
|
||||
*/
|
||||
function mimemail_rules_action_mail_to_user_upgrade_map_name($element) {
|
||||
return 'mimemail';
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_rules_action_base_upgrade_map_name().
|
||||
*/
|
||||
function mimemail_rules_action_mail_to_users_of_role_upgrade_map_name($element) {
|
||||
return 'mimemail_to_users_of_role';
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_rules_action_base_upgrade().
|
||||
*/
|
||||
function mimemail_rules_action_mail_upgrade($element, RulesPlugin $target) {
|
||||
$target->settings['key'] = $element['#settings']['key'];
|
||||
$target->settings['from_name'] = $element['#settings']['sender'];
|
||||
$target->settings['from_mail'] = $element['#settings']['from'];
|
||||
$target->settings['body'] = $element['#settings']['message_html'];
|
||||
$target->settings['plaintext'] = $element['#settings']['message_plaintext'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_rules_action_base_upgrade().
|
||||
*/
|
||||
function mimemail_rules_action_mail_to_user_upgrade($element, RulesPlugin $target) {
|
||||
switch ($element['#settings']['#argument map']['user']) {
|
||||
case 'author':
|
||||
$token = 'node:author';
|
||||
break;
|
||||
case 'author_unchanged':
|
||||
$token = 'node-unchanged:author';
|
||||
break;
|
||||
case 'user':
|
||||
$token = 'site:current-user';
|
||||
break;
|
||||
}
|
||||
$target->settings['to:select'] = $token . ':mail';
|
||||
mimemail_rules_action_mail_upgrade($element, $target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_rules_action_base_upgrade().
|
||||
*/
|
||||
function mimemail_rules_action_mail_to_users_of_role_upgrade($element, RulesPlugin $target) {
|
||||
$target->settings['roles'] = $element['#settings']['recipients'];
|
||||
mimemail_rules_action_mail_upgrade($element, $target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Action Implementation: Send HTML mail.
|
||||
*/
|
||||
function rules_action_mimemail($key, $to, $cc = NULL, $bcc = NULL, $from_name = NULL, $from_mail = NULL, $reply_to = NULL, $subject, $body, $plaintext = NULL, $attachments = array(), $langcode, $settings, RulesState $state, RulesPlugin $element) {
|
||||
module_load_include('inc', 'mimemail');
|
||||
|
||||
// Set the sender name and from address.
|
||||
if (empty($from_mail)) {
|
||||
$from = NULL;
|
||||
}
|
||||
else {
|
||||
$from = array(
|
||||
'name' => $from_name,
|
||||
'mail' => $from_mail,
|
||||
);
|
||||
// Create an address string.
|
||||
$from = mimemail_address($from);
|
||||
}
|
||||
|
||||
// Figure out the language to use - fallback is the system default.
|
||||
$languages = language_list();
|
||||
$language = isset($languages[$langcode]) ? $languages[$langcode] : language_default();
|
||||
|
||||
$params = array(
|
||||
'context' => array(
|
||||
'subject' => $subject,
|
||||
'body' => $body,
|
||||
'action' => $element,
|
||||
'state' => $state,
|
||||
),
|
||||
'cc' => $cc,
|
||||
'bcc' => $bcc,
|
||||
'reply-to' => $reply_to,
|
||||
'plaintext' => $plaintext,
|
||||
'attachments' => $attachments,
|
||||
);
|
||||
|
||||
drupal_mail('mimemail', $key, $to, $language, $params, $from);
|
||||
}
|
||||
|
||||
/**
|
||||
* Action: Send HTML mail to all users of a specific role group(s).
|
||||
*/
|
||||
function rules_action_mimemail_to_users_of_role($key, $roles, $active, $from_name = NULL, $from_mail = NULL, $subject, $body, $plaintext = NULL, $attachments = array(), $use_userlang = FALSE, $langcode= NULL, $settings, RulesState $state, RulesPlugin $element) {
|
||||
module_load_include('inc', 'mimemail');
|
||||
|
||||
// Set the sender name and from address.
|
||||
if (empty($from_mail)) {
|
||||
$from = NULL;
|
||||
}
|
||||
else {
|
||||
$from = array(
|
||||
'name' => $from_name,
|
||||
'mail' => $from_mail,
|
||||
);
|
||||
// Create an address string.
|
||||
$from = mimemail_address($from);
|
||||
}
|
||||
|
||||
$query = db_select('users', 'u');
|
||||
$query->fields('u', array('mail', 'language'));
|
||||
|
||||
if ($active) {
|
||||
$query->condition('u.status', 1, '=');
|
||||
}
|
||||
|
||||
if (in_array(DRUPAL_AUTHENTICATED_RID, $roles)) {
|
||||
$query->condition('u.uid', 0, '>');
|
||||
}
|
||||
else {
|
||||
$query->join('users_roles', 'r', 'u.uid = r.uid');
|
||||
$query->condition('r.rid', $roles, 'IN');
|
||||
$query->distinct();
|
||||
}
|
||||
|
||||
$result = $query->execute();
|
||||
|
||||
$params = array(
|
||||
'context' => array(
|
||||
'subject' => $subject,
|
||||
'body' => $body,
|
||||
'action' => $element,
|
||||
'state' => $state,
|
||||
),
|
||||
'plaintext' => $plaintext,
|
||||
'attachments' => $attachments,
|
||||
);
|
||||
|
||||
// Create language list before initializing foreach.
|
||||
$languages = language_list();
|
||||
|
||||
$message = array('result' => TRUE);
|
||||
foreach ($result as $row) {
|
||||
// Decide which language to use.
|
||||
if (!$use_userlang || empty($row->language) || !isset($languages[$row->language])) {
|
||||
$language = isset($languages[$langcode]) ? $languages[$langcode] : language_default();
|
||||
}
|
||||
else {
|
||||
$language = $languages[$row->language];
|
||||
}
|
||||
|
||||
$message = drupal_mail('mimemail', $key, $row->mail, $language, $params, $from);
|
||||
if (!$message['result']) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($message['result']) {
|
||||
$role_names = array_intersect_key(user_roles(TRUE), array_flip($roles));
|
||||
watchdog('rules', 'Successfully sent HTML email to the role(s) %roles.', array('%roles' => implode(', ', $role_names)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
@@ -0,0 +1,14 @@
|
||||
name = "Mime Mail Action"
|
||||
description = "Provide actions for Mime Mail."
|
||||
package = Mail
|
||||
dependencies[] = mimemail
|
||||
dependencies[] = trigger
|
||||
core = 7.x
|
||||
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-09-06
|
||||
version = "7.x-1.0-alpha2+30-dev"
|
||||
core = "7.x"
|
||||
project = "mimemail"
|
||||
datestamp = "1378431585"
|
||||
|
@@ -0,0 +1,193 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Provide actions for Mime Mail.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_action_info().
|
||||
*/
|
||||
function mimemail_action_info() {
|
||||
return array(
|
||||
'mimemail_send_email_action' => array(
|
||||
'type' => 'system',
|
||||
'label' => t('Send HTML e-mail'),
|
||||
'configurable' => TRUE,
|
||||
'triggers' => array('any'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements a configurable Drupal action. Sends an email.
|
||||
*/
|
||||
function mimemail_send_email_action($entity, $context) {
|
||||
if (empty($context['node'])) {
|
||||
$context['node'] = $entity;
|
||||
}
|
||||
|
||||
$to = token_replace($context['to'], $context);
|
||||
|
||||
// If the recipient is a registered user with a language preference, use
|
||||
// the recipient's preferred language. Otherwise, use the system default
|
||||
// language.
|
||||
$account = user_load_by_mail($to);
|
||||
if ($account) {
|
||||
$language = user_preferred_language($account);
|
||||
}
|
||||
else {
|
||||
$language = language_default();
|
||||
}
|
||||
|
||||
$params = array(
|
||||
'context' => array(
|
||||
'subject' => token_replace($context['subject'], $context),
|
||||
'body' => token_replace($context['body'], $context),
|
||||
),
|
||||
'key' => $context['key'],
|
||||
'cc' => $context['cc'],
|
||||
'bcc' => $context['bcc'],
|
||||
'reply-to' => $context['reply-to'],
|
||||
'plaintext' => token_replace($context['plaintext'], $context),
|
||||
'attachments' => $context['attachments'],
|
||||
);
|
||||
|
||||
drupal_mail('mimemail', $context['key'], $to, $language, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Form for configurable Drupal action to send an HTML mail.
|
||||
*/
|
||||
function mimemail_send_email_action_form($context) {
|
||||
$context += array(
|
||||
'key' => '',
|
||||
'to' => '',
|
||||
'cc' => '',
|
||||
'bcc' => '',
|
||||
'reply-to' => '',
|
||||
'subject' => '',
|
||||
'body' => '',
|
||||
'format' => filter_fallback_format(),
|
||||
'plaintext' => '',
|
||||
'attachments' => ''
|
||||
);
|
||||
|
||||
$form['key'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Key'),
|
||||
'#default_value' => $context['key'],
|
||||
'#description' => t('A key to identify the e-mail sent.'),
|
||||
'#required' => TRUE,
|
||||
);
|
||||
$form['to'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Recipient'),
|
||||
'#default_value' => $context['to'],
|
||||
'#maxlength' => 254,
|
||||
'#description' => t('The email address to which the message should be sent OR enter [node:author:mail], [comment:author:mail], etc. if you would like to send an e-mail to the author of the original post.'),
|
||||
'#required' => TRUE,
|
||||
);
|
||||
$form['cc'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('CC Recipient'),
|
||||
'#default_value' => $context['cc'],
|
||||
'#description' => t("The mail's carbon copy address. You may separate multiple addresses with comma."),
|
||||
'#required' => FALSE,
|
||||
);
|
||||
$form['bcc'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('BCC Recipient'),
|
||||
'#default_value' => $context['bcc'],
|
||||
'#description' => t("The mail's blind carbon copy address. You may separate multiple addresses with comma."),
|
||||
'#required' => FALSE,
|
||||
);
|
||||
$form['reply-to'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Reply e-mail address'),
|
||||
'#default_value' => $context['reply-to'],
|
||||
'#description' => t("The address to reply to. Leave it empty to use the sender's address."),
|
||||
'#required' => FALSE,
|
||||
);
|
||||
$form['subject'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Subject'),
|
||||
'#maxlength' => 254,
|
||||
'#default_value' => $context['subject'],
|
||||
'#description' => t("The subject of the message."),
|
||||
);
|
||||
$form['body'] = array(
|
||||
'#type' => 'text_format',
|
||||
'#title' => t('Body'),
|
||||
'#default_value' => $context['body'],
|
||||
'#format' => $context['format'],
|
||||
'#description' => t('The HTML message that should be sent. You may include placeholders like [node:title], [user:name], and [comment:body] to represent data that will be different each time message is sent. Not all placeholders will be available in all contexts.'),
|
||||
);
|
||||
$form['plaintext'] = array(
|
||||
'#type' => 'textarea',
|
||||
'#title' => t('Plain text body'),
|
||||
'#default_value' => $context['plaintext'],
|
||||
'#description' => t('Optional plaintext portion of a multipart message. You may include placeholders like [node:title], [user:name], and [comment:body] to represent data that will be different each time message is sent. Not all placeholders will be available in all contexts.'),
|
||||
);
|
||||
$form['attachments'] = array(
|
||||
'#type' => 'textarea',
|
||||
'#title' => t('Attachments'),
|
||||
'#default_value' => $context['attachments'],
|
||||
'#description' => t('A list of attachments, one file per line e.g. "files/images/mypic.png" without quotes.'),
|
||||
);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the action form.
|
||||
*/
|
||||
function mimemail_send_email_action_validate($form, $form_state) {
|
||||
$to = trim($form_state['values']['to']);
|
||||
if (!valid_email_address($to) && strpos($to, ':mail') === FALSE) {
|
||||
form_set_error('to', t('Enter a valid email address or use a token e-mail address such as %author.', array('%author' => '[node:author:mail]')));
|
||||
}
|
||||
|
||||
$cc = explode(',', $form_state['values']['cc']);
|
||||
foreach ($cc as $recipient) {
|
||||
$recipient = trim($recipient);
|
||||
if (!empty($recipient) && !valid_email_address($recipient) && strpos($recipient, ':mail') === FALSE) {
|
||||
form_set_error('cc', t('Enter a valid email address or use a token e-mail address such as %author.', array('%author' => '[node:author:mail]')));
|
||||
}
|
||||
}
|
||||
|
||||
$bcc = explode(',', $form_state['values']['bcc']);
|
||||
foreach ($bcc as $recipient) {
|
||||
$recipient = trim($recipient);
|
||||
if (!empty($recipient) && !valid_email_address($recipient) && strpos($recipient, ':mail') === FALSE) {
|
||||
form_set_error('bcc', t('Enter a valid email address or use a token e-mail address such as %author.', array('%author' => '[node:author:mail]')));
|
||||
}
|
||||
}
|
||||
|
||||
$reply_to = trim($form_state['values']['reply-to']);
|
||||
if (!empty($reply_to) && !valid_email_address($reply_to) && strpos($reply_to, ':mail') === FALSE) {
|
||||
form_set_error('reply-to', t('Enter a valid email address or use a token e-mail address such as %author.', array('%author' => '[node:author:mail]')));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle submission of the action form.
|
||||
*/
|
||||
function mimemail_send_email_action_submit($form, $form_state) {
|
||||
$form_values = $form_state['values'];
|
||||
|
||||
$params = array(
|
||||
'key' => $form_values['key'],
|
||||
'to' => $form_values['to'],
|
||||
'cc' => $form_values['cc'],
|
||||
'bcc' => $form_values['bcc'],
|
||||
'reply-to' => $form_values['reply-to'],
|
||||
'subject' => $form_values['subject'],
|
||||
'body' => $form_values['body']['value'],
|
||||
'format' => $form_values['body']['format'],
|
||||
'plaintext' => $form_values['plaintext'],
|
||||
'attachments' => $form_values['attachments'],
|
||||
);
|
||||
|
||||
return $params;
|
||||
}
|
@@ -0,0 +1,259 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Converts CSS styles into inline style attributes.
|
||||
*
|
||||
* Code based on Emogrifier by Pelago Design (http://www.pelagodesign.com).
|
||||
*/
|
||||
|
||||
/**
|
||||
* Separate CSS from HTML for processing
|
||||
*/
|
||||
function mimemail_compress_clean_message($message) {
|
||||
$parts = array();
|
||||
preg_match('|(<style[^>]+)>(.*)</style>|mis', $message, $matches);
|
||||
if (isset($matches[0]) && isset($matches[2])) {
|
||||
$css = str_replace('<!--', '', $matches[2]);
|
||||
$css = str_replace('-->', '', $css);
|
||||
$css = preg_replace('|\{|', "\n{\n", $css);
|
||||
$css = preg_replace('|\}|', "\n}\n", $css);
|
||||
$html = str_replace($matches[0], '', $message);
|
||||
$parts = array('html' => $html, 'css' => $css);
|
||||
}
|
||||
return $parts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compress HTML and CSS into combined message
|
||||
*/
|
||||
class mimemail_compress {
|
||||
private $html = '';
|
||||
private $css = '';
|
||||
private $unprocessable_tags = array('wbr');
|
||||
|
||||
public function mimemail_compress($html = '', $css = '') {
|
||||
$this->html = $html;
|
||||
$this->css = $css;
|
||||
}
|
||||
|
||||
// There are some HTML tags that DOMDocument cannot process,
|
||||
// and will throw an error if it encounters them.
|
||||
// These functions allow you to add/remove them if necessary.
|
||||
// It only strips them from the code (does not remove actual nodes).
|
||||
public function add_unprocessable_tag($tag) {
|
||||
$this->unprocessable_tags[] = $tag;
|
||||
}
|
||||
|
||||
public function remove_unprocessable_tag($tag) {
|
||||
if (($key = array_search($tag, $this->unprocessable_tags)) !== FALSE) {
|
||||
unset($this->unprocessableHTMLTags[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
public function compress() {
|
||||
if (!class_exists('DOMDocument', FALSE)) {
|
||||
return $this->html;
|
||||
}
|
||||
|
||||
$body = $this->html;
|
||||
// Process the CSS here, turning the CSS style blocks into inline CSS.
|
||||
if (count($this->unprocessable_tags)) {
|
||||
$unprocessable_tags = implode('|', $this->unprocessable_tags);
|
||||
$body = preg_replace("/<($unprocessable_tags)[^>]*>/i", '', $body);
|
||||
}
|
||||
|
||||
$err = error_reporting(0);
|
||||
$doc = new DOMDocument();
|
||||
|
||||
// Try to set character encoding.
|
||||
if (function_exists('mb_convert_encoding')) {
|
||||
$body = mb_convert_encoding($body, 'HTML-ENTITIES', "UTF-8");
|
||||
$doc->encoding= "UTF-8";
|
||||
}
|
||||
|
||||
$doc->strictErrorChecking = FALSE;
|
||||
$doc->formatOutput = TRUE;
|
||||
$doc->loadHTML($body);
|
||||
$doc->normalizeDocument();
|
||||
|
||||
$xpath = new DOMXPath($doc);
|
||||
|
||||
// Get rid of comments.
|
||||
$css = preg_replace('/\/\*.*\*\//sU', '', $this->css);
|
||||
|
||||
// Process the CSS file for selectors and definitions.
|
||||
preg_match_all('/^\s*([^{]+){([^}]+)}/mis', $css, $matches);
|
||||
|
||||
$all_selectors = array();
|
||||
foreach ($matches[1] as $key => $selector_string) {
|
||||
// If there is a blank definition, skip.
|
||||
if (!strlen(trim($matches[2][$key]))) continue;
|
||||
// Else split by commas and duplicate attributes so we can sort by selector precedence.
|
||||
$selectors = explode(',', $selector_string);
|
||||
foreach ($selectors as $selector) {
|
||||
// Don't process pseudo-classes.
|
||||
if (strpos($selector, ':') !== FALSE) continue;
|
||||
$all_selectors[] = array(
|
||||
'selector' => $selector,
|
||||
'attributes' => $matches[2][$key],
|
||||
'index' => $key, // Keep track of where it appears in the file, since order is important.
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Now sort the selectors by precedence.
|
||||
usort($all_selectors, array('self', 'sort_selector_precedence'));
|
||||
|
||||
// Before we begin processing the CSS file, parse the document for inline
|
||||
// styles and append the normalized properties (i.e., 'display: none'
|
||||
// instead of 'DISPLAY: none') as selectors with full paths (highest
|
||||
// precedence), so they override any file-based selectors.
|
||||
$nodes = @$xpath->query('//*[@style]');
|
||||
if ($nodes->length > 0) {
|
||||
foreach ($nodes as $node) {
|
||||
$style = preg_replace_callback('/[A-z\-]+(?=\:)/S', create_function('$matches', 'return strtolower($matches[0]);'), $node->getAttribute('style'));
|
||||
$all_selectors[] = array(
|
||||
'selector' => $this->calculateXPath($node),
|
||||
'attributes' => $style,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($all_selectors as $value) {
|
||||
// Query the body for the xpath selector.
|
||||
$nodes = $xpath->query($this->css_to_xpath(trim($value['selector'])));
|
||||
|
||||
foreach ($nodes as $node) {
|
||||
// If it has a style attribute, get it, process it, and append (overwrite) new stuff.
|
||||
if ($node->hasAttribute('style')) {
|
||||
// Break it up into an associative array.
|
||||
$old_style = $this->css_style_to_array($node->getAttribute('style'));
|
||||
$new_style = $this->css_style_to_array($value['attributes']);
|
||||
// New styles overwrite the old styles (not technically accurate, but close enough).
|
||||
$compressed = array_merge($old_style, $new_style);
|
||||
$style = '';
|
||||
foreach ($compressed as $k => $v) {
|
||||
$style .= (drupal_strtolower($k) . ':' . $v . ';');
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Otherwise create a new style.
|
||||
$style = trim($value['attributes']);
|
||||
}
|
||||
$node->setAttribute('style', $style);
|
||||
}
|
||||
}
|
||||
|
||||
// This removes styles from your email that contain display:none. You could comment these out if you want.
|
||||
$nodes = $xpath->query('//*[contains(translate(@style," ",""), "display:none")]');
|
||||
foreach ($nodes as $node) {
|
||||
$node->parentNode->removeChild($node);
|
||||
}
|
||||
|
||||
if (variable_get('mimemail_preserve_class', 0) == FALSE) {
|
||||
$nodes = $xpath->query('//*[@class]');
|
||||
foreach ($nodes as $node) {
|
||||
$node->removeAttribute('class');
|
||||
}
|
||||
}
|
||||
|
||||
error_reporting($err);
|
||||
|
||||
return $doc->saveHTML();
|
||||
}
|
||||
|
||||
private static function sort_selector_precedence($a, $b) {
|
||||
$precedenceA = self::get_selector_precedence($a['selector']);
|
||||
$precedenceB = self::get_selector_precedence($b['selector']);
|
||||
|
||||
// We want these sorted ascendingly so selectors with lesser precedence get processed first and selectors with greater precedence get sorted last.
|
||||
return ($precedenceA == $precedenceB) ? ($a['index'] < $b['index'] ? -1 : 1) : ($precedenceA < $precedenceB ? -1 : 1);
|
||||
}
|
||||
|
||||
private static function get_selector_precedence($selector) {
|
||||
$precedence = 0;
|
||||
$value = 100;
|
||||
// Ids: worth 100, classes: worth 10, elements: worth 1.
|
||||
$search = array('\#', '\.', '');
|
||||
|
||||
foreach ($search as $s) {
|
||||
if (trim($selector == '')) break;
|
||||
$num = 0;
|
||||
$selector = preg_replace('/' . $s . '\w+/', '', $selector, -1, $num);
|
||||
$precedence += ($value * $num);
|
||||
$value /= 10;
|
||||
}
|
||||
|
||||
return $precedence;
|
||||
}
|
||||
|
||||
/**
|
||||
* Right now we only support CSS 1 selectors, but include CSS2/3 selectors are fully possible.
|
||||
*
|
||||
* @see http://plasmasturm.org/log/444
|
||||
*/
|
||||
private function css_to_xpath($selector) {
|
||||
if (drupal_substr($selector, 0, 1) == '/') {
|
||||
// Already an XPath expression.
|
||||
return $selector;
|
||||
}
|
||||
// Returns an Xpath selector.
|
||||
$search = array(
|
||||
'/\s+>\s+/', // Matches any F element that is a child of an element E.
|
||||
'/(\w+)\s+\+\s+(\w+)/', // Matches any F element that is a child of an element E.
|
||||
'/\s+/', // Matches any F element that is a descendant of an E element.
|
||||
'/(\w)\[(\w+)\]/', // Matches element with attribute.
|
||||
'/(\w)\[(\w+)\=[\'"]?(\w+)[\'"]?\]/', // Matches element with EXACT attribute.
|
||||
'/(\w+)?\#([\w\-]+)/e', // Matches id attributes.
|
||||
'/(\w+|\*)?((\.[\w\-]+)+)/e', // Matches class attributes.
|
||||
);
|
||||
$replace = array(
|
||||
'/',
|
||||
'\\1/following-sibling::*[1]/self::\\2',
|
||||
'//',
|
||||
'\\1[@\\2]',
|
||||
'\\1[@\\2="\\3"]',
|
||||
"(strlen('\\1') ? '\\1' : '*').'[@id=\"\\2\"]'",
|
||||
"(strlen('\\1') ? '\\1' : '*').'[contains(concat(\" \",normalize-space(@class),\" \"),concat(\" \",\"'.implode('\",\" \"))][contains(concat(\" \",normalize-space(@class),\" \"),concat(\" \",\"',explode('.',substr('\\2',1))).'\",\" \"))]'",
|
||||
);
|
||||
return '//' . preg_replace($search, $replace, trim($selector));
|
||||
}
|
||||
|
||||
private function css_style_to_array($style) {
|
||||
$definitions = explode(';', $style);
|
||||
$css_styles = array();
|
||||
foreach ($definitions as $def) {
|
||||
if (empty($def) || strpos($def, ':') === FALSE) continue;
|
||||
list($key, $value) = explode(':', $def, 2);
|
||||
if (empty($key) || empty($value)) continue;
|
||||
$css_styles[trim($key)] = trim($value);
|
||||
}
|
||||
return $css_styles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the full path to a DOM node.
|
||||
*
|
||||
* @param DOMNode $node
|
||||
* The node to analyze.
|
||||
*
|
||||
* @return string
|
||||
* The full xpath to a DOM node.
|
||||
*
|
||||
* @see http://stackoverflow.com/questions/2643533/php-getting-xpath-of-a-domnode
|
||||
*/
|
||||
function calculateXPath(DOMNode $node) {
|
||||
$xpath = '';
|
||||
$q = new DOMXPath($node->ownerDocument);
|
||||
|
||||
do {
|
||||
$position = 1 + $q->query('preceding-sibling::*[name()="' . $node->nodeName . '"]', $node)->length;
|
||||
$xpath = '/' . $node->nodeName . '[' . $position . ']' . $xpath;
|
||||
$node = $node->parentNode;
|
||||
}
|
||||
while (!$node instanceof DOMDocument);
|
||||
|
||||
return $xpath;
|
||||
}
|
||||
}
|
@@ -0,0 +1,14 @@
|
||||
name = Mime Mail CSS Compressor
|
||||
description = Converts CSS to inline styles in an HTML message. (Requires the PHP DOM extension.)
|
||||
package = Mail
|
||||
dependencies[] = mimemail
|
||||
core = 7.x
|
||||
|
||||
files[] = mimemail_compress.inc
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-09-06
|
||||
version = "7.x-1.0-alpha2+30-dev"
|
||||
core = "7.x"
|
||||
project = "mimemail"
|
||||
datestamp = "1378431585"
|
||||
|
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Install, update and uninstall functions for Mime Mail Compress module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_requirements().
|
||||
*/
|
||||
function mimemail_compress_requirements($phase) {
|
||||
$requirements = array();
|
||||
// Ensure translations don't break at install time.
|
||||
$t = get_t();
|
||||
|
||||
// Test PHP DOM extension.
|
||||
if (extension_loaded('dom')) {
|
||||
$requirements['dom']['value'] = $t('Enabled');
|
||||
}
|
||||
else {
|
||||
$requirements['dom'] = array(
|
||||
'description' => $t('Mime Mail Compress requires the PHP DOM extension to be enabled.'),
|
||||
'severity' => REQUIREMENT_ERROR,
|
||||
'value' => $t('Disabled'),
|
||||
);
|
||||
}
|
||||
|
||||
$requirements['dom']['title'] = $t('PHP DOM extension');
|
||||
|
||||
return $requirements;
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Component module for sending Mime-encoded emails.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements mail_post_process().
|
||||
*/
|
||||
function mimemail_compress_mail_post_process(&$message, $mailkey) {
|
||||
module_load_include('inc', 'mimemail_compress');
|
||||
// Separate CSS from HTML for processing.
|
||||
$parts = mimemail_compress_clean_message($message);
|
||||
// Compress HTML and CSS into combined message.
|
||||
if (!empty($parts)) {
|
||||
$output = new mimemail_compress($parts['html'], $parts['css']);
|
||||
$output = $output->compress();
|
||||
$message = $output;
|
||||
}
|
||||
}
|
46
sites/all/modules/contrib/mail/mimemail/tests/mimemail.test
Normal file
46
sites/all/modules/contrib/mail/mimemail/tests/mimemail.test
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Functionality tests for the Mime Mail module.
|
||||
*
|
||||
* @ingroup mimemail
|
||||
*/
|
||||
|
||||
require_once(dirname(__FILE__) . '/../mimemail.inc');
|
||||
|
||||
/**
|
||||
* Tests helper functions from the Mime Mail module.
|
||||
*/
|
||||
class MimeMailUnitTestCase extends DrupalUnitTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Mime Mail unit tests',
|
||||
'description' => 'Test that Mime Mail helper functions work properly.',
|
||||
'group' => 'Mime Mail',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
drupal_load('module', 'mimemail');
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
function testHeaders() {
|
||||
// Test the regular expression for extracting the mail address.
|
||||
$chars = array('-', '.', '+', '_');
|
||||
$name = $this->randomString();
|
||||
$local = $this->randomName() . $chars[array_rand($chars)] . $this->randomName();
|
||||
$domain = $this->randomName() . '-' . $this->randomName() . '.' . $this->randomName(rand(2,4));
|
||||
$headers = mimemail_headers(array(), "$name <$local@$domain>");
|
||||
$result = $headers['Return-Path'];
|
||||
$expected = "<$local@$domain>";
|
||||
$this->assertIdentical($result, $expected, 'Return-Path header field correctly set.');
|
||||
}
|
||||
|
||||
function testUrl() {
|
||||
$result = _mimemail_url('#');
|
||||
$this->assertIdentical($result, '#', 'Hash mark URL without fragment left intact.');
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Functionality tests for the Mime Mail Compress module.
|
||||
*
|
||||
* @ingroup mimemail
|
||||
*/
|
||||
|
||||
require_once(dirname(__FILE__) . '/../modules/mimemail_compress/mimemail_compress.inc');
|
||||
|
||||
/**
|
||||
* Tests helper functions from the Mime Mail Compress module.
|
||||
*/
|
||||
class MimeMailCompressUnitTestCase extends DrupalUnitTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Mime Mail Compress unit tests',
|
||||
'description' => 'Test that Mime Mail Compress helper functions work properly.',
|
||||
'group' => 'Mime Mail',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
drupal_load('module', 'mimemail_compress');
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,225 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Functionality tests for the Rules integration in the Mime Mail module.
|
||||
*
|
||||
* @ingroup mimemail
|
||||
*/
|
||||
|
||||
/**
|
||||
* Tests the Rules integration.
|
||||
*/
|
||||
class MimeMailRulesTestCase extends DrupalWebTestCase {
|
||||
/**
|
||||
* The user with administration permissions.
|
||||
* @var object
|
||||
*/
|
||||
protected $adminUser;
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Rules integration',
|
||||
'description' => 'Test the Rules integration.',
|
||||
'group' => 'Mime Mail',
|
||||
);
|
||||
}
|
||||
|
||||
public function setUp(array $modules = array()) {
|
||||
$modules[] = 'mailsystem';
|
||||
$modules[] = 'locale';
|
||||
$modules[] = 'entity';
|
||||
$modules[] = 'entity_token';
|
||||
$modules[] = 'rules';
|
||||
$modules[] = 'mimemail';
|
||||
parent::setUp($modules);
|
||||
|
||||
// Create and login user.
|
||||
$this->adminUser = $this->drupalCreateUser(array(
|
||||
'access administration pages',
|
||||
'edit mimemail user settings',
|
||||
'administer languages',
|
||||
'administer rules',
|
||||
'bypass rules access',
|
||||
'access rules debug',
|
||||
));
|
||||
$this->drupalLogin($this->adminUser);
|
||||
|
||||
// Enable another language too.
|
||||
foreach (array('de', 'it') as $langcode) {
|
||||
$edit = array();
|
||||
$edit['langcode'] = $langcode;
|
||||
$this->drupalPost('admin/config/regional/language/add', $edit, t('Add language'));
|
||||
}
|
||||
|
||||
// Make sure we are not using a stale list.
|
||||
drupal_static_reset('language_list');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create mimemail action rule and fire it.
|
||||
*/
|
||||
public function testMimemailAction() {
|
||||
$settings = array(
|
||||
'key' => 'mail-key-' . $this->randomName(),
|
||||
'to' => $this->randomName() . '@example.com',
|
||||
'from' => $this->randomName() . '@example.com',
|
||||
'subject' => $this->randomName(),
|
||||
'body' => $this->randomName(60) . '<div></div><br /><hr>',
|
||||
'plaintext' => $this->randomName(30) . '<div></div><br /><hr>',
|
||||
);
|
||||
|
||||
|
||||
// Set no language for the mail and check if the system default is used.
|
||||
$rule = rule();
|
||||
$rule->action('mimemail', array(
|
||||
'key' => $settings['key'],
|
||||
'to' => $settings['to'],
|
||||
'from_mail' => $settings['from'],
|
||||
'subject' => $settings['subject'],
|
||||
'body' => $settings['body'],
|
||||
'plaintext' => $settings['plaintext'],
|
||||
'language' => '',
|
||||
))->save();
|
||||
|
||||
$rule->execute();
|
||||
$mails = $this->drupalGetMails(array('key' => $settings['key']));
|
||||
$this->assertEqual(count($mails), 1);
|
||||
$mail = reset($mails);
|
||||
$this->assertEqual($mail['to'], $settings['to']);
|
||||
$this->assertEqual($mail['from'], $settings['from']);
|
||||
$this->assertEqual($mail['subject'], $settings['subject']);
|
||||
$this->assertEqual($mail['params']['context']['body'], $settings['body']);
|
||||
$this->assertEqual($mail['params']['plaintext'], $settings['plaintext']);
|
||||
$this->assertEqual($mail['language']->language, language_default('language'));
|
||||
|
||||
// Explicitly set another language for the mail.
|
||||
$rule_action = $rule->elementMap()->lookup(3);
|
||||
unset($rule_action->settings['language:select']);
|
||||
$rule_action->settings['language'] = 'de';
|
||||
$rule_action->settings['key'] = $settings['key'];
|
||||
$rule->save();
|
||||
$rule->execute();
|
||||
$mails = $this->drupalGetMails(array('key' => $settings['key']));
|
||||
$this->assertEqual(count($mails), 2);
|
||||
$mail = end($mails);
|
||||
$this->assertEqual($mail['language']->language, 'de');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create mimemail to users by role action rule and fire it.
|
||||
*/
|
||||
public function testMimemaiToUsersOfRoleAction() {
|
||||
$languages = language_list();
|
||||
|
||||
// Add more uses and roles.
|
||||
$users = array(
|
||||
$this->randomName() . '@example.com' => 'en',
|
||||
$this->randomName() . '@example.com' => 'de',
|
||||
$this->randomName() . '@example.com' => 'it',
|
||||
$this->randomName() . '@example.com' => '',
|
||||
$this->randomName() . '@example.com' => 'invalid',
|
||||
);
|
||||
$mimemail_role = $this->drupalCreateRole(array());
|
||||
foreach ($users as $email => $language) {
|
||||
$user = $this->drupalCreateUser(array(
|
||||
'access administration pages',
|
||||
));
|
||||
$user->language = $language;
|
||||
$user->mail = $email;
|
||||
$user->roles[$mimemail_role] = $mimemail_role;
|
||||
user_save($user);
|
||||
}
|
||||
$settings = array(
|
||||
'key' => 'mail-key-' . $this->randomName(),
|
||||
'from' => $this->randomName() . '@example.com',
|
||||
'subject' => $this->randomName(),
|
||||
'body' => $this->randomName(60) . '<div></div><br /><hr>',
|
||||
'plaintext' => $this->randomName(30) . '<div></div><br /><hr>',
|
||||
);
|
||||
// Rest the collected mails.
|
||||
variable_set('drupal_test_email_collector', array());
|
||||
|
||||
// Send mails to all users of a role and respect the language of the users.
|
||||
// Don't enforce a specific language as fallback use the system default.
|
||||
$rule = rule();
|
||||
$rule->action('mimemail_to_users_of_role', array(
|
||||
'key' => $settings['key'],
|
||||
'from_mail' => $settings['from'],
|
||||
'subject' => $settings['subject'],
|
||||
'body' => $settings['body'],
|
||||
'plaintext' => $settings['plaintext'],
|
||||
'roles' => array($mimemail_role => $mimemail_role),
|
||||
'active' => TRUE,
|
||||
'language_user' => TRUE,
|
||||
'language' => '',
|
||||
));
|
||||
$rule->save();
|
||||
$rule->execute();
|
||||
$mails = $this->drupalGetMails(array('key' => $settings['key']));
|
||||
$this->assertEqual(count($mails), count($users));
|
||||
$mail = reset($mails);
|
||||
$this->assertEqual($mail['from'], $settings['from']);
|
||||
$this->assertEqual($mail['subject'], $settings['subject']);
|
||||
$this->assertEqual($mail['params']['context']['body'], $settings['body']);
|
||||
$this->assertEqual($mail['params']['plaintext'], $settings['plaintext']);
|
||||
foreach ($mails as $mail) {
|
||||
// If the user hasn't a proper language the system default has to be used
|
||||
// if the rules action doesn't provide a language to use.
|
||||
$user_language = (!empty($languages[$users[$mail['to']]])) ? $users[$mail['to']] : language_default('language');
|
||||
$this->assertEqual($mail['language']->language, $user_language);
|
||||
}
|
||||
|
||||
// Send mails to all users of a role and respect the language of the users.
|
||||
// Enforce German as fallback language if an user doesn't have a language.
|
||||
// Rest the collected mails.
|
||||
variable_set('drupal_test_email_collector', array());
|
||||
$rule->elementMap()->lookup(3)->settings['language'] = 'de';
|
||||
$rule->save();
|
||||
$rule->execute();
|
||||
$mails = $this->drupalGetMails(array('key' => $settings['key']));
|
||||
$this->assertEqual(count($mails), count($users));
|
||||
foreach ($mails as $mail) {
|
||||
// If the user hasn't a proper language the language set in the rules
|
||||
// action has to be used.
|
||||
$user_language = (!empty($languages[$users[$mail['to']]])) ? $users[$mail['to']] : 'de';
|
||||
$this->assertEqual($mail['language']->language, $user_language);
|
||||
}
|
||||
|
||||
// Send mails to all users of a role but use the same language for all.
|
||||
// Rest the collected mails.
|
||||
variable_set('drupal_test_email_collector', array());
|
||||
$rule->elementMap()->lookup(3)->settings['language_user'] = FALSE;
|
||||
$rule->elementMap()->lookup(3)->settings['language'] = 'it';
|
||||
$rule->save();
|
||||
$rule->execute();
|
||||
$mails = $this->drupalGetMails(array('key' => $settings['key']));
|
||||
foreach ($mails as $mail) {
|
||||
$this->assertEqual($mail['language']->language, 'it');
|
||||
}
|
||||
|
||||
// Send mails to all users of a role except deactivated users.
|
||||
// Rest the collected mails.
|
||||
variable_set('drupal_test_email_collector', array());
|
||||
// Disable one of the users.
|
||||
reset($users);
|
||||
$user = user_load_by_mail(key($users));
|
||||
$user->status = 0;
|
||||
user_save($user);
|
||||
$rule->execute();
|
||||
$mails = $this->drupalGetMails(array('key' => $settings['key']));
|
||||
$this->assertEqual(count($mails), count($users) - 1);
|
||||
|
||||
// Rest the collected mails.
|
||||
variable_set('drupal_test_email_collector', array());
|
||||
|
||||
// Send mails to all users, also to deactivated ones.
|
||||
$rule->elementMap()->lookup(3)->settings['active'] = FALSE;
|
||||
$rule->save();
|
||||
$rule->execute();
|
||||
$mails = $this->drupalGetMails(array('key' => $settings['key']));
|
||||
// One user is disabled but it should be ignored.
|
||||
$this->assertEqual(count($mails), count($users));
|
||||
}
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Default theme implementation to format an HTML mail.
|
||||
*
|
||||
* Copy this file in your default theme folder to create a custom themed mail.
|
||||
* Rename it to mimemail-message--[module]--[key].tpl.php to override it for a
|
||||
* specific mail.
|
||||
*
|
||||
* Available variables:
|
||||
* - $recipient: The recipient of the message
|
||||
* - $subject: The message subject
|
||||
* - $body: The message body
|
||||
* - $css: Internal style sheets
|
||||
* - $module: The sending module
|
||||
* - $key: The message identifier
|
||||
*
|
||||
* @see template_preprocess_mimemail_message()
|
||||
*/
|
||||
?>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<?php if ($css): ?>
|
||||
<style type="text/css">
|
||||
<!--
|
||||
<?php print $css ?>
|
||||
-->
|
||||
</style>
|
||||
<?php endif; ?>
|
||||
</head>
|
||||
<body id="mimemail-body" <?php if ($module && $key): print 'class="'. $module .'-'. $key .'"'; endif; ?>>
|
||||
<div id="center">
|
||||
<div id="main">
|
||||
<?php print $body ?>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
154
sites/all/modules/contrib/mail/mimemail/theme/mimemail.theme.inc
Normal file
154
sites/all/modules/contrib/mail/mimemail/theme/mimemail.theme.inc
Normal file
@@ -0,0 +1,154 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* The theme system, which controls the output of the messages.
|
||||
*/
|
||||
|
||||
function mimemail_theme_theme() {
|
||||
$path = drupal_get_path('module', 'mimemail') . '/theme';
|
||||
|
||||
return array(
|
||||
'mimemail_message' => array(
|
||||
'variables' => array('module' => NULL, 'key' => NULL, 'recipient' => NULL, 'subject' => NULL, 'body' => NULL),
|
||||
'template' => 'mimemail-message',
|
||||
'pattern' => 'mimemail_message__',
|
||||
'file' => 'mimemail.theme.inc',
|
||||
'mail theme' => TRUE,
|
||||
'path' => $path,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* A preprocess function for theme('mimemail_message').
|
||||
*
|
||||
* The $variables array initially contains the following arguments:
|
||||
* - $recipient: The recipient of the message
|
||||
* - $key: The mailkey associated with the message
|
||||
* - $subject: The message subject
|
||||
* - $body: The message body
|
||||
*
|
||||
* @see mimemail-message.tpl.php
|
||||
*/
|
||||
function template_preprocess_mimemail_message(&$variables) {
|
||||
$theme = mailsystem_get_mail_theme();
|
||||
$themepath = drupal_get_path('theme', $theme);
|
||||
|
||||
$sitestyle = variable_get('mimemail_sitestyle', 1);
|
||||
$mailstyles = file_scan_directory($themepath, '#^mail\.css*$#');
|
||||
|
||||
// Check recursively for the existence of a mail.css file in the theme folder.
|
||||
if (!empty($mailstyles)) {
|
||||
foreach ($mailstyles as $mailstyle) {
|
||||
$styles = $mailstyle->uri;
|
||||
}
|
||||
}
|
||||
// If no mail.css was found and the site style sheets including is enabled,
|
||||
// gather all style sheets and embed a version of all style definitions.
|
||||
elseif ($sitestyle) {
|
||||
// Grab local.css if it exists (support for Fusion based themes).
|
||||
$local = $themepath . '/css/local.css';
|
||||
if (@file_exists($local)) {
|
||||
$css_all = drupal_add_css($local, array('group' => CSS_THEME));
|
||||
}
|
||||
else {
|
||||
$css_all = drupal_add_css();
|
||||
}
|
||||
$css_files = array();
|
||||
foreach ($css_all as $key => $options) {
|
||||
if ($options['group'] == CSS_THEME && $options['type'] == 'file' &&
|
||||
($options['media'] == 'all' || $options['media'] == 'screen')) {
|
||||
$css_files[$key] = $options;
|
||||
}
|
||||
}
|
||||
if (variable_get('preprocess_css', FALSE)) {
|
||||
$pattern = '|<link.*href="' . $GLOBALS['base_url'] . '/([^"?]*)[?"].*|';
|
||||
$replacement = '\1';
|
||||
}
|
||||
else {
|
||||
$pattern = array(
|
||||
'/<([^<>]*)>/', // Remove the style tag.
|
||||
'/@import\s+url\("([^"]+)"\);+/', // Remove the import directive.
|
||||
'|' . $GLOBALS['base_url'] . '/([^"?]*)[?"].*|' // Remove the base URL.
|
||||
);
|
||||
$replacement = array('', '\1', '\1');
|
||||
}
|
||||
$styles = preg_replace($pattern, $replacement, drupal_get_css($css_files));
|
||||
}
|
||||
|
||||
$css = '';
|
||||
if (isset($styles)) {
|
||||
// Process each style sheet.
|
||||
foreach (explode("\n", $styles) as $style) {
|
||||
if (!empty($style) && @file_exists($style)) {
|
||||
$css .= @file_get_contents($style);
|
||||
}
|
||||
}
|
||||
|
||||
// Regexp to match comment blocks.
|
||||
$comment = '/\*[^*]*\*+(?:[^/*][^*]*\*+)*/';
|
||||
// Regexp to match double quoted strings.
|
||||
$double_quot = '"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"';
|
||||
// Regexp to match single quoted strings.
|
||||
$single_quot = "'[^'\\\\]*(?:\\\\.[^'\\\\]*)*'";
|
||||
|
||||
// Perform some safe CSS optimizations (derived from core CSS aggregation).
|
||||
$css = preg_replace_callback(
|
||||
"<$double_quot|$single_quot|$comment>Sus", // Match all comment blocks along
|
||||
"_mimemail_process_comment", // with double/single quoted strings
|
||||
$css); // and feed them to _mimemail_process_comment().
|
||||
$css = preg_replace(
|
||||
'<\s*([@{}:;,]|\)\s|\s\()\s*[^\n\S]>S', // Remove whitespace around separators,
|
||||
'\1', // but keep space around parentheses
|
||||
$css); // and new lines between definitions.
|
||||
|
||||
// End the file with a new line.
|
||||
$css .= "\n";
|
||||
|
||||
// Wordwrap to adhere to RFC821
|
||||
$css = wordwrap($css, 700);
|
||||
}
|
||||
|
||||
// Set styles for the message.
|
||||
$variables['css'] = $css;
|
||||
|
||||
// Set template alternatives.
|
||||
$variables['theme_hook_suggestions'][] = 'mimemail_message__' . str_replace('-', '_', $variables['key']);
|
||||
|
||||
// Process identifiers to be proper CSS classes.
|
||||
$variables['module'] = str_replace('_', '-', $variables['module']);
|
||||
$variables['key'] = str_replace('_', '-', $variables['key']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process comment blocks. (derived from core CSS aggregation)
|
||||
*
|
||||
* This is the callback function for the preg_replace_callback()
|
||||
* used in drupal_load_stylesheet_content(). Support for comment
|
||||
* hacks is implemented here.
|
||||
*/
|
||||
function _mimemail_process_comment($matches) {
|
||||
static $keep_nextone = FALSE;
|
||||
// Quoted string, keep it.
|
||||
if ($matches[0][0] == "'" || $matches[0][0] == '"') {
|
||||
return $matches[0];
|
||||
}
|
||||
// End of IE-Mac hack, keep it.
|
||||
if ($keep_nextone) {
|
||||
$keep_nextone = FALSE;
|
||||
return $matches[0];
|
||||
}
|
||||
switch (strrpos($matches[0], '\\')) {
|
||||
case FALSE :
|
||||
// No backslash, strip it.
|
||||
return '';
|
||||
case drupal_strlen($matches[0])-3 :
|
||||
// Ends with \*/ so is a multi line IE-Mac hack, keep the next one also.
|
||||
$keep_nextone = TRUE;
|
||||
return '/*_\*/';
|
||||
default :
|
||||
// Single line IE-Mac hack.
|
||||
return '/*\_*/';
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user