email - Grails 电子邮件的 DRY 布局?

标签 email grails layout

我正在尝试清理我的 grails 项目中的一些电子邮件 View 。我的团队对每封电子邮件都使用相同的介绍、 Logo 和签名。我尝试将它们放入传统的 grails 布局文件中,并使用元标记 <meta name="layout" content="email"/> 调用它,但它似乎不起作用。有没有另一种方法可以为这些电子邮件模板创建一个单一的布局?

最佳答案

我试图弄清楚你所说的 DRY 是什么意思,我认为它一定是一些 ruby 术语,我猜你的意思是模板。

HTML 电子邮件的问题实际上是跨所有语言的标准问题,就像在包含 Logo (页眉/页脚)时一样。标准各不相同,虽然它可能适用于某些邮件客户端,但可能不适用于例如 web 邮件,即 gmail 等。

诀窍是使用内联图像,我将为您提供一些示例内容:

所以这是一个示例 Controller - 这是我自己的代码,但来自不同的部分。这是为了给您一个想法,或者我应该说不是很好地专门针对多内联图像进行了解释:

class Mycontroller() { 
   pivate final static String TEMPLATE='/emails/emailTemplate'
   def emailService
   def doEmail() { 
    def images=[]
    //Where this list contains a map of photo Ids(could be macde up, the photo content type and actual photo file Names (to go and grab from uploaded folder)
    images <<[id: "uImage${photo.id}", contentType: "${photo.contentType}", file: photo.file]
    images <<[id: "uImage${photo1.id}", contentType: "${photo1.contentType}", file: photo1.file]
    emailService.sendEmail(user.email, subject, TEMPLATE, [instance: bean, domainName:domainName, fqdn:fqdn ], images)
  }
}

我有一个列表,如果上面的图像包含照片 ID、内容类型和实际文件名(以文本形式)发送到 emailService.sendEmail
private void sendEmail(email,mysubject,template,templateModel,List images) throws Exception {
        List<String> recipients = []       
        try {
            mailService.sendMail {
                //this must be set true and at the top for inline images to work
                multipart true
                if (recipients) {
                    to recipients
                }
                else {
                    to email
                }
                if (config.admin.emailFrom) {
                    if (Environment.current == Environment.DEVELOPMENT && config.admin.emailFromDev ) {
                        from "${config.admin.emailFromDev}"
                    } else {
                        from "${config.admin.emailFrom}"
                    }
                }
                subject mysubject
                //actual content must be html sent to fill in a grails template
                html Holders.grailsApplication.mainContext.groovyPageRenderer.render(template: template, model: templateModel)
                //Main Site logo
                inline 'inlineImage', 'image/png', new File("/opt/site-stuff/myLogo.png")
                //Additional images 
                if (images) {
                    images?.each { a ->
                        inline "${a.id}", "${a.contentType}", new File("${a.file}")
                    }
                }
            }
        }
        catch (e) {
            //throw new Exception(e.message)
            log.error "Problem sending email ${e.message}"
        }
    }

现在,您认为可以像在布局中那样使用 grails 模板的部分不是您想要的,如上所述,您可以看到它正在呈现模板,但模板是典型的 gsp 模板,而不是一个完整的 html 页面:

/电子邮件/电子邮件模板
<%@ page contentType="text/html;charset=UTF-8" %>
<!doctype html>
<html>
<head>
<style>
    .site-icon img {
        width: 300px;
        margin-top:-50px;
    }
    .site-logo img {
        min-width: 25em;
        max-width: 45em;
    }
    .menu {
        background: #CCC;
    }
    a {
        text-decoration: none;
    }
    .menu a {
        color : #FF0000;
        text-decoration: none;
        font-weight:bold;
    }
    .menu a:hover {
        color : #00FFFF;
        background: #ccc;
    }    
</style>
</head>
<body style=" background-color: blue; font-size: 1.0em;">
<table  width="100%" border="0" cellpadding="0" cellspacing="0" bgcolor="#FFFFFF">
    <tr style="background: red;"><td colspan="3" class="site-logo">
        <img src="cid:inlineImage"/>
        <h1 style="display:inline; margin-top:-2em;"><g:message code="domain.label"/></h1>
    </td>
    </tr>

      <g:each in="${instance.results}" var="user" status="ii">
      <tr><td>
       <div class="image">
                    <g:if test="${user.profilePhoto}">
                        <img src="cid:uImage${user.id}"/>
                    </g:if>
                </div>

           </td></tr>

      </g:each>
</table>

您会看到 html 电子邮件的主要问题是 CSS 样式不能很好地工作,它在某些情况下可以工作,但在很多情况下,您最好还是坚持使用传统表格并使用样式标签来正确声明您的布局。

忘记使用您的实际站点 CSS 文件,因为就此过程而言,这是直接生成和发送的电子邮件。它不知道您的站点 CSS 文件。

关于我们正在谈论的多个图像

这是用户列表

usera {usera 照片}/userA 描述
userb {userb 照片}/userB 描述

上述解决方案将拥有您添加执行此操作所需的所有内联图像所需的一切。这意味着您要在电子邮件中附加图像,因此如果图像很大,那么您也要附加它们,因此诀窍是重新格式化图像/调整它们的大小。

对于您自己的网站 Logo ,您可以直接执行此操作,并拥有一个单独的文件/文件夹,其中包含要通过电子邮件发送的实际大小,但对于动态调整大小,您可以尝试以下操作:
   static Map getPhoto(Photos photo, int width=100,int height=100) {
        File f
        def contentType
        if (photo.status==Photos.ACTIVE) {
            def id = photo.id
            def imageSHa = photo.imageSHa
            contentType = photo.contentType
            def fileExtension = photo.fileExtension
            //remove . from fileExtension
            def noDotExtension = fileExtension.substring(1)
            def user = photo.user
            f = new File(ROOT_PATH + '/' + user.username + '/' + imageSHa);
            if (f.exists() && !f.isDirectory()) {
                f = new File(ROOT_PATH + '/' + user.username + '/' + imageSHa+'_email');
                if (!f.exists()) {
                    def imageStream = new FileInputStream(ROOT_PATH + '/' + user.username + '/' + imageSHa)
                    def image = FileCopyUtils.copyToByteArray(imageStream).encodeBase64().toString()
                    def caption = photo.caption
                    def position = photo.position
                    // String caption=photo.caption
                    //Lets present the image as a thumbNail
                    imageStream = new FileInputStream(ROOT_PATH + '/' + user.username + '/' + imageSHa)
                    def imageBuffer = ImageIO.read(imageStream)
                    def scaledImg = Scalr.resize(imageBuffer, Scalr.Method.QUALITY, width, height, Scalr.OP_ANTIALIAS)
                    ByteArrayOutputStream os = new ByteArrayOutputStream();
                    ImageIO.write(scaledImg, noDotExtension, os)
                    InputStream is = new ByteArrayInputStream(os.toByteArray())

                    def scaledImage = FileCopyUtils.copyToByteArray(is).encodeBase64().toString()
                    //imageSHa = DigestUtils.shaHex(scaledImg)
                    byte[] data = Base64.decodeBase64(scaledImage)
                    OutputStream stream = new FileOutputStream(ROOT_PATH + '/' + user.username + '/' + imageSHa+'_email')
                    stream.write(data)
                    f = new File(ROOT_PATH + '/' + user.username + '/' + imageSHa+'_email');
                }
                return [file:f, contentType:'img/'+fileExtension.substring(1)]
            }

        }
        return [:]
    }

这现在映射到我在上面进行图像映射时:
 def res = PhotosBean.getPhoto(ui.attributes.profilePhoto)
                            if (res) {
                                images << [id: "uImage${ui.id}", contentType: "${res.contentType}", file: res.file]
                            }

希望这可以消除我必须经历的很多头痛,以实现具有所需数量的图像的 html 电子邮件,并且所有图像都调整为我想要的大小

关于email - Grails 电子邮件的 DRY 布局?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37755341/

相关文章:

email - 如何在 Go 中验证电子邮件地址

grails - SHA1编码数据并在grails View 中访问哈希结果

html - 设置div 100%的窗口内容不会溢出

Jquery UI 使用 Cookie 保存状态

android - RelativeLayout 的子级未填充 RelativeLayout 的高度

Python 电子邮件模块 : form header "From" with some unicode name + email

java - 解析电子邮件中签名部分的图像

php - 如何使用php同时向同一张 table 上的2个人发送电子邮件

authentication - 如何在 Grails 中使用 Spring Security 检查用户在线状态?

jquery - Grails jQuery的更改