请选择 进入手机版 | 继续访问电脑版

网络科技

    今日:358| 主题:285769
收藏本版
互联网、科技极客的综合动态。

[其他] Building Your Startup: Refining Email Templates

[复制链接]
我是ゝ高富帥 发表于 2016-10-20 01:00:59
414 9

Building Your Startup: Refining Email Templates

Building Your Startup: Refining Email Templates-1-网络科技-the,Templates,Meeting,and,Email
      What You'll Be Creating       This tutorial is part of the Building Your Startup With PHP series on Envato Tuts+. In this series, I'm guiding you through launching a startup from concept to reality using my  Meeting Planner app as a real-life example. Every step along the way, I'll release the Meeting Planner code as open-source examples you can learn from. I'll also address startup-related business issues as they arise.
   In this tutorial, I'll be refining the responsive, HTML email templates that Meeting Planner uses to send out invitations, notifications, reminders, and account-related messages.
  During the initial stage of Meeting Planner development, I've focused primarily on functionality and have not yet invested significantly in design or hired a designer. Today's goal is to clean up the appearance of the existing HTML templates so that the basic emails are more readable and usable for people.
  Likely half of people's first experience with Meeting Planner will be via a Meeting Request email.
   If you haven't tried out Meeting Planner yet, go ahead and schedule your first meeting . I do participate in the comment threads below, so tell me what you think! You can also reach me on  Twitter @reifman . I'm especially interested if you want to suggest new features or topics for future tutorials.
   As a reminder, all of the code for Meeting Planner is written in the Yii2 Framework for PHP. If you'd like to learn more about Yii2, check out our parallel series Programming With Yii2 .
  Messages and Templates

  The Early Templates

   Initially, I used basic frameworks I found on the web to create early emails for Meeting Planner. They worked acceptably for the early development phase.
  Here's an example of our existing HTML emails; they're functional but not very appealing. And, overall, I've decided that people don't need this many options and links within their invitations. It was time to reduce the plethora of options for a simpler experience.
     

Building Your Startup: Refining Email Templates

Building Your Startup: Refining Email Templates-2-网络科技-the,Templates,Meeting,and,Email
    Even with the templates I'd used, email tables often appeared corrupted without easy explanation:
     

Building Your Startup: Refining Email Templates

Building Your Startup: Refining Email Templates-3-网络科技-the,Templates,Meeting,and,Email
    I'd been preparing to migrate to more professional email templates, but it was definitely overdue.
  The Variety of Messages

  Here's a summary of the messages that Meeting Planner regularly sends today:
  
       
  • meeting requests (i.e. invitations)   
  • meeting updates for changes ( also known as notifications )   
  • meeting confirmations with calendar file attachment   
  • meeting reminders   
  • requests for contact information for an upcoming meeting   
  • password reset requests  
  For the alpha test, I'm hoping I can reach a reasonable aesthetic baseline by applying open-source templates to be found on the web. At a later date, we'll hire a designer to invigorate the templates, theme and brand together.
  I began scouring the web for the best email templates.
  Open-Source Template Resources

  There are a number of helpful guides like these:
  
       
  • 30 Free Responsive Email and NewsletterTemplates (SpeckyBoy)   
  • 12 Completely Free Email Templates Resources (Iterable)  
  And a number of providers offer open-source templates of their own:
  
       
  • Mailgun Transactional HTML Email Templates     
  • Sendwithus Open Source Email Templates   
  • Litmus Community Templates  and Free Responsive Templates   
  • Mailchimp/email-blueprints: HTML Email Layouts by MailChimp  
   Initially, I was drawn to the Mailgun templates as I felt they were thoroughly tested and I could build on them, but ultimately, I decided to go with Sendwithus's Oxygen email templates . Sendwithus is a synergistic marketing platform for Mailgun(or potentially other email providers), but I don't have experience with their overall service.
  Oxygen offered a complete family of templates for useful scenarios. It seemed simple, organized, and easily extensible:
     

Building Your Startup: Refining Email Templates

Building Your Startup: Refining Email Templates-4-网络科技-the,Templates,Meeting,and,Email
    It's kind of them to offer their open-source email templates without requiring you to be a paying user. Go open source!
  Integrating the New Templates

  As an MVC framework, Yii separates layouts from body content. So I needed to break down the templates and monitor differences between variations within a group.
   You can download the Oxygen family of templates from the  Sendwithus GitHub , but they've not clearly divided the standard style elements common to each template, so you have to do that yourself.
  It took some time to choose which templates I preferred, which elements I liked in each, and which CSS should be integrated into the layout.
  Separating the Layout

  Ultimately, here's the new HTML layout (I've truncated the styles here for readability):
  1. <?php
  2. use yii\helpers\Html;
  3. /* @var $this \yii\web\View view component instance */
  4. /* @var $message \yii\mail\MessageInterface the message being composed */
  5. /* @var $content string main view render result */
  6. ?>
  7. <?php $this->beginPage(); ?>
  8. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  9. <html xmlns="http://www.w3.org/1999/xhtml">
  10. <head>
  11.   <meta http-equiv="Content-Type" content="text/html; charset=<?php echo Yii::$app->charset; ?>" />
  12.   <meta name="viewport" content="width=device-width, initial-scale=1" />
  13.   <title><?php echo Html::encode($this->title); ?></title>
  14.   <?php $this->head(); ?>
  15.     <style type="text/css">
  16.   ...
  17. </style>
  18. <link rel="stylesheet" media="screen" type="text/css" href="http://fonts.googleapis.com/css?family=Oxygen:400,700">
  19. ...
  20. </head>
  21. <body>
  22. <?php $this->beginBody(); ?>
  23. <body bgcolor="#f7f7f7">
  24. <table align="center" cellpadding="0" cellspacing="0" class="container-for-gmail-android" width="100%">
  25.   <tr>
  26.     <td align="left" valign="top" width="100%" style="background:repeat-x url(https://meetingplanner.io/img/bg_top_02.jpg) #ffffff;">
  27.       <center>
  28.         <?= Html::img('https://meetingplanner.io/img/transparent.png', ['class'=>'force-width-gmail']);?>
  29.         <table cellspacing="0" cellpadding="0" width="100%" bgcolor="#ffffff" background="https://meetingplanner.io/img/bg_top_02.jpg" style="background-color:transparent">
  30.           <tr>
  31.             <td width="100%" height="80" valign="top" style="text-align: center; vertical-align:middle;">
  32.             <!--[if gte mso 9]>
  33.             <v:rect xmlns:v="urn:schemas-microsoft-com:vml" fill="true" stroke="false" style="mso-width-percent:1000;height:80px; v-text-anchor:middle;">
  34.               <v:fill type="tile" src="http://s3.amazonaws.com/swu-filepicker/4E687TRe69Ld95IDWyEg_bg_top_02.jpg" color="#ffffff" />
  35.               <v:textbox inset="0,0,0,0">
  36.             <![endif]-->
  37.               <center>
  38.                 <table cellpadding="0" cellspacing="0" width="600" class="w320">
  39.                   <tr>
  40.                     <td class="pull-left mobile-header-padding-left" style="vertical-align: middle;">
  41.                       <a href="https://meetingplanner.io"><?= Html::img('https://meetingplanner.io/img/email-logo.gif', ['alt'=>'Meeting Planner logo','height'=>'47','width'=>'137']);?></a>
  42.                     </td>
  43.                     <td class="pull-right mobile-header-padding-right" style="color: #4d4d4d;">
  44.                       <a href="https://twitter.com/intent/user?screen_name=meetingio"><?= Html::img('https://meetingplanner.io/img/social_twitter.gif', ['alt'=>[email protected] on twitter','height'=>'47','width'=>'38']);?></a>
  45.                       <!-- <a href=""><img width="38" height="47" src="http://s3.amazonaws.com/swu-filepicker/LMPMj7JSRoCWypAvzaN3_social_09.gif" alt="facebook" /></a>-->
  46.                       <!-- <a href=""><img width="40" height="47" src="http://s3.amazonaws.com/swu-filepicker/hR33ye5FQXuDDarXCGIW_social_10.gif" alt="rss" /></a>-->
  47.                     </td>
  48.                   </tr>
  49.                 </table>
  50.               </center>
  51.               <!--[if gte mso 9]>
  52.               </v:textbox>
  53.             </v:rect>
  54.             <![endif]-->
  55.             </td>
  56.           </tr>
  57.         </table>
  58.       </center>
  59.     </td>
  60.   </tr>
  61. <?php echo $content; ?>
  62. </table>
  63. <?php $this->endBody(); ?>
  64. </body>
  65. </html>
  66. <?php $this->endPage(); ?>
复制代码
Replacing the Common Elements

  Within the templates, I had to replace a number of elements:
  
       
  • Logo   
  • Supporting images   
  • Links  
  I created a logo file that would work for now, and I statically hosted it and the helper images, e.g. for Twitter, on Meeting Planner's server.
     

Building Your Startup: Refining Email Templates

Building Your Startup: Refining Email Templates-5-网络科技-the,Templates,Meeting,and,Email
    I also replaced the default links within the email with code for our site links.
  Building a Footer Section

  To simplify reuse across the application, I separated the code for the footer:
  1. <?php
  2. use yii\helpers\Html;
  3. use yii\helpers\Url;
  4. use common\components\MiscHelpers;
  5. ?>
  6. <tr>
  7.   <td align="center" valign="top" width="100%" style="background-color: #f7f7f7; height: 100px;">
  8.     <center>
  9.       <table cellspacing="0" cellpadding="0" width="600" class="w320">
  10.         <tr>
  11.           <td style="padding: 25px 0 15px">
  12.             <strong><?php echo Html::a(Yii::t('frontend','Meeting Planner'), $links['home']); ?></strong><br />
  13.             Seattle, Washington<br />
  14.           </td>
  15.         </tr>
  16.         <tr><td style="font-size:75%;"><em>
  17.           <?php echo HTML::a(Yii::t('frontend','Email settings'),$links['footer_email']); ?>
  18.           | <?php echo HTML::a(Yii::t('frontend','Block sender'),$links['footer_block']); ?>
  19.           <?php //echo HTML::a(Yii::t('frontend','Block all'),$links['footer_block_all']); ?>
  20.         </em>
  21.         </td></tr>
  22.       </table>
  23.     </center>
  24.   </td>
  25. </tr>
复制代码
Updating the Existing Templates

  To integrate the templates, I wanted to start with the easiest one. Moving around complex, unfamiliar CSS and HTML is never simple.
  I began with our Password Reset email template.
  Password Reset

  I chose Oxygen's Welcome template shown below:
     

Building Your Startup: Refining Email Templates

Building Your Startup: Refining Email Templates-6-网络科技-the,Templates,Meeting,and,Email
     Each of SendwithUs's individual templates can be previewed and tested on their Litmus account .
  Here's our reset your password email now on an iPhone, much more aesthetically comfortable than before:
     

Building Your Startup: Refining Email Templates

Building Your Startup: Refining Email Templates-7-网络科技-the,Templates,Meeting,and,Email
    I was a bit confused when the first Gmail attempts I received looked malformed to me.
     

Building Your Startup: Refining Email Templates

Building Your Startup: Refining Email Templates-8-网络科技-the,Templates,Meeting,and,Email
     But reviewing their Litmus previews showed me that that's what they look like in Gmail :
     

Building Your Startup: Refining Email Templates

Building Your Startup: Refining Email Templates-9-网络科技-the,Templates,Meeting,and,Email
    I later learned that Gmail requires more inlining of CSS than other services. I'll guide you through repairing this in a future tutorial.
  Here's the passwordRequestToken.php code that helped generate the above:
  1. <?php
  2. use yii\helpers\Html;
  3. /* @var $this yii\web\View */
  4. /* @var $user common\models\User */
  5. $resetLink = Yii::$app->urlManager->createAbsoluteUrl(['site/reset-password', 'token' => $user->password_reset_token]);
  6. ?>
  7. <tr>
  8.   <td align="center" valign="top" width="100%" style="background-color: #f7f7f7;" class="content-padding">
  9.     <center>
  10.       <table cellspacing="0" cellpadding="0" width="600" class="w320">
  11.         <tr>
  12.           <td class="header-lg">
  13.             Reset Your Password
  14.           </td>
  15.         </tr>
  16.         <tr>
  17.           <td class="free-text">
  18.             Hello <?php echo Html::encode(\common\components\MiscHelpers::getDisplayName($user->id)); ?>,
  19.             Click the button below to reset your Meeting Planner password:
  20.           </td>
  21.         </tr>
  22.         <tr>
  23.           <td class="button">
  24.             <div><!--[if mso]>
  25.               <v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="http://" style="height:45px;v-text-anchor:middle;width:155px;" arcsize="15%" strokecolor="#ffffff" fillcolor="#ff6f6f">
  26.                 <w:anchorlock/>
  27.                 <center style="color:#ffffff;font-family:Helvetica, Arial, sans-serif;font-size:14px;font-weight:regular;">My Account</center>
  28.               </v:roundrect>
  29.             <![endif]--><a class="button-mobile" href="<?php echo $resetLink ?>"
  30.             style="background-color:#ff6f6f;border-radius:5px;color:#ffffff;display:inline-block;font-family:'Cabin', Helvetica, Arial, sans-serif;font-size:14px;font-weight:regular;line-height:45px;text-align:center;text-decoration:none;width:155px;-webkit-text-size-adjust:none;mso-hide:all;">Reset Your Password</a></div>
  31.           </td>
  32.         </tr>
  33.       </table>
  34.     </center>
  35.   </td>
  36. </tr>
  37. <tr>
  38.   <td align="center" valign="top" width="100%" style="background-color: #ffffff;  border-top: 1px solid #e5e5e5; border-bottom: 1px solid #e5e5e5;">
  39.     <center>
  40.       <br />
  41.     </center>
  42.   </td>
  43. </tr>
  44. <?php echo \Yii::$app->view->renderFile([email protected]/mail/section-footer-static.php') ?>
复制代码
The Meeting Request

  The invitation people receive as a request to meet is our most complex template. It's sharing a brief introduction, possible places, possible times, and sometimes a note.
  For this, I used the Oxygen Confirm template:
     

Building Your Startup: Refining Email Templates

Building Your Startup: Refining Email Templates-10-网络科技-the,Templates,Meeting,and,Email
    I thought the Shipping and Date Shipped boxes could be used for sharing Place and Date Time options, and it's worked fairly well.
  Here's what the invitation looks like now:
     

Building Your Startup: Refining Email Templates

Building Your Startup: Refining Email Templates-11-网络科技-the,Templates,Meeting,and,Email
    Certainly, the basic aesthetic appearance is much better. In the future, I may do some work to level and equalize the vertical heights of the places and date times boxes.
  Here's the invitation-html.php body code that helped generate the above:
  1. <?php
  2. use yii\helpers\Html;
  3. use yii\helpers\Url;
  4. use common\components\MiscHelpers;
  5. use frontend\models\Meeting;
  6. use frontend\models\MeetingNote;
  7. use frontend\models\MeetingPlace;
  8. use frontend\models\MeetingTime;
  9. /* @var $this \yii\web\View view component instance */
  10. /* @var $message \yii\mail\BaseMessage instance of newly created mail message */
  11. ?>
  12. <tr>
  13.   <td align="center" valign="top" width="100%" style="background-color: #f7f7f7;" class="content-padding">
  14.     <center>
  15.       <table cellspacing="0" cellpadding="0" width="600" class="w320">
  16.         <tr>
  17.           <td class="header-lg">
  18.             Your Meeting Request
  19.           </td>
  20.         </tr>
  21.         <tr>
  22.           <td class="free-text">
  23.             <p><em>Hi, <?php echo $owner; ?> is inviting you to an event using a new service called <?php echo HTML::a(Yii::t('frontend','Meeting Planner'),MiscHelpers::buildCommand($meeting_id,Meeting::COMMAND_HOME,0,$user_id,$auth_key)); ?>. The service makes it easy to plan meetings without the exhausting threads of repetitive emails. Please try it out below.</em></p>
  24.             <p><?php echo $intro; ?></p>
  25.           </td>
  26.         </tr>
  27.         <tr>
  28.           <td class="button">
  29.             <div><!--[if mso]>
  30.               <v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="http://" style="height:45px;v-text-anchor:middle;width:155px;" arcsize="15%" strokecolor="#ffffff" fillcolor="#ff6f6f">
  31.                 <w:anchorlock/>
  32.                 <center style="color:#ffffff;font-family:Helvetica, Arial, sans-serif;font-size:14px;font-weight:regular;">Track Order</center>
  33.               </v:roundrect>
  34.             <![endif]--><a href="<?php echo $links['view']; ?>" style="background-color:#ff6f6f;border-radius:5px;color:#ffffff;display:inline-block;font-family:'Cabin', Helvetica, Arial, sans-serif;font-size:14px;font-weight:regular;line-height:45px;text-align:center;text-decoration:none;width:155px;-webkit-text-size-adjust:none;mso-hide:all;"><?php echo Yii::t('frontend','View Request')?></a>
  35.           </div>
  36.           </td>
  37.         </tr>
  38.         <tr>
  39.           <td class="w320">
  40.             <table cellpadding="0" cellspacing="0" width="100%">
  41.               <tr>
  42.                 <td class="mini-container-left">
  43.                   <table cellpadding="0" cellspacing="0" width="100%">
  44.                     <tr>
  45.                       <td class="mini-block-padding">
  46.                         <table cellspacing="0" cellpadding="0" width="100%" style="border-collapse:separate !important;">
  47.                           <tr>
  48.                             <td class="mini-block">
  49.                               <span class="header-sm">Possible Times</span><br />
  50.                               <?php
  51.                                 foreach($times as $t) {
  52.                                   ?>
  53.                                       <?php echo Meeting::friendlyDateFromTimestamp($t->start); ?><br />
  54.                                       <?php
  55.                                     }
  56.                                 ?>
  57.                                 <?php // echo HTML::a(Yii::t('frontend','accept all times'),$links['accepttimes']); ?>
  58.                                 <br />
  59.                                 <?php
  60.                                 if ($meetingSettings->participant_add_date_time) { ?>
  61.                                 <?php echo HTML::a(Yii::t('frontend','suggest a time'),$links['addtime']); ?><br />
  62.                                 <?php
  63.                                 }
  64.                                 ?>
  65.                             </td>
  66.                           </tr>
  67.                         </table>
  68.                       </td>
  69.                     </tr>
  70.                   </table>
  71.                 </td>
  72.                 <td class="mini-container-right">
  73.                   <table cellpadding="0" cellspacing="0" width="100%">
  74.                     <tr>
  75.                       <td class="mini-block-padding">
  76.                         <table cellspacing="0" cellpadding="0" width="100%" style="border-collapse:separate !important;">
  77.                           <tr>
  78.                             <td class="mini-block">
  79.                               <span class="header-sm">Possible Places</span><br />
  80.                               <?php
  81.                               if (!$noPlaces) {
  82.                               ?>
  83.                               <?php
  84.                                 foreach($places as $p) {
  85.                                   ?>
  86.                                       <?php echo $p->place->name.' '; ?>
  87.                                       <span style="font-size:75%;"><?php echo $p->place->vicinity; ?> <?php echo HTML::a(Yii::t('frontend','map'),
  88.                                       MiscHelpers::buildCommand($meeting_id,Meeting::COMMAND_VIEW_MAP,$p->id,$user_id,$auth_key)); ?></span><br />
  89.                                 <?php
  90.                                     }
  91.                                 ?>
  92.                                 <br />
  93.                                 <?php // echo HTML::a(Yii::t('frontend','accept all places'),$links['acceptplaces']); ?><br />
  94.                                 <?php
  95.                                 if ($meetingSettings->participant_add_place) { ?>
  96.                                 <?php echo HTML::a(Yii::t('frontend','suggest a place'),$links['addplace']); ?><br />
  97.                                 <?php
  98.                                 }
  99.                                 ?>
  100.                                 <?php
  101.                               } else {
  102.                                   ?>
  103.                                   Phone or video <br />
  104.                               <?php
  105.                                 }
  106.                               ?>
  107.                             </td>
  108.                           </tr>
  109.                         </table>
  110.                       </td>
  111.                     </tr>
  112.                   </table>
  113.                 </td>
  114.               </tr>
  115.             </table>
  116.           </td>
  117.         </tr>
  118.         <tr>
  119.           <td class="free-text">
  120.             <?php
  121.                 if (!$noPlaces) {
  122.                     echo HTML::a(Yii::t('frontend','Accept all places and times'),$links['acceptall']).' | ';
  123.                 }
  124.              ?>
  125.                <?php
  126.                if ($meetingSettings->participant_finalize && count($places)==1 && count($times)==1) {
  127.                 echo HTML::a(Yii::t('frontend','Finalize meeting'),$links['finalize']).' | ';
  128.                }
  129.                ?>
  130.                <?php echo HTML::a(Yii::t('frontend','Decline request'),$links['decline']); ?>
  131.           </td>
  132.         </tr>

  133.         <?php echo \Yii::$app->view->renderFile([email protected]/mail/section-notes.php',['notes'=>$notes,'links'=>$links]) ?>
  134.       </table>
  135.     </center>
  136.   </td>
  137. </tr>
  138. <?php echo \Yii::$app->view->renderFile([email protected]/mail/section-footer-dynamic.php',['links'=>$links]) ?>
复制代码
What's Next?

  Now that the basic templates have been updated, I'll begin working to repair their appearances in Gmail. And soon, we'll implement notifications and reminders using them.
   While you're waiting for episodes about these features, schedule your first meeting and try out the new templates. Also, I'd appreciate it if you share your experience below in the comments, and I'm always interested in your suggestions. You can also reach me on Twitter  @reifman directly.
   I'm also beginning to experiment with WeFunder based on the implementation of the SEC's new crowdfunding rules . Please consider following our profile . I may write about this more as part of our series.
   Watch for upcoming tutorials in the Building Your Startup With PHP series . There are a few more big features coming up.
不理朝的王爷 发表于 2016-10-20 01:11:17
楼上的别说的那么悲观好吧!
回复 支持 反对

使用道具 举报

lee007lee 发表于 2016-10-20 01:41:01
我在外边都用手机上来酷辣虫顶我是ゝ高富帥!
回复 支持 反对

使用道具 举报

vanilla1989 发表于 2016-10-20 01:41:05
2016-10-20是什么日子?
回复 支持 反对

使用道具 举报

冯怡 发表于 2016-10-20 02:19:13
星期四加班灌水!
回复 支持 反对

使用道具 举报

方力眠n 发表于 2016-10-20 02:40:56
鸟大了,什么林子都敢进啊!
回复 支持 反对

使用道具 举报

福章修 发表于 2016-11-6 01:35:03
我只是路过,不发表意见
回复 支持 反对

使用道具 举报

挑逗女人的心 发表于 2016-11-9 02:51:44
高手云集 果断围观
回复 支持 反对

使用道具 举报

贾东 发表于 2016-11-13 03:49:13
沙发君,我来啦,想我了木?
回复 支持 反对

使用道具 举报

与世界格格不入 发表于 2016-11-21 20:23:38
我听说这种帖子不能沉!
回复 支持 反对

使用道具 举报

我要投稿

推荐阅读


回页顶回复上一篇下一篇回列表
手机版/c.CoLaBug.com ( 粤ICP备05003221号 | 文网文[2010]257号 | 粤公网安备 44010402000842号 )

© 2001-2017 Comsenz Inc.

返回顶部 返回列表