Grails电子邮件的干燥布局?

时间:2016-06-10 18:52:15

标签: email grails layout

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

1 个答案:

答案 0 :(得分:0)

我试图找出DRY的意思,我认为它必须是一些红宝石术语,我想你的意思是模板。

HTML电子邮件的问题实际上是一个标准问题,包括所有语言,包括徽标(页眉/页脚)。标准各不相同,虽然它可能适用于某些邮件客户端可能无法使用例如web邮件,即gmail等。

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

所以这是一个示例控制器 - 这是我自己的代码,但来自不同的部分。它是给你一个想法,或者我应该说没有很好地解释多个内联图像:

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页面:

/电子邮件/的emailTemplate

<%@ 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 Photo} / userA说明 userb {userb Photo} / userB Description

上述解决方案将为您提供所需的全部内联图像。这意味着您正在将图像附加到电子邮件中,因此如果图像很大,那么您还要附加它们,这样就可以重新格式化图像/调整图像大小。

对于您自己的网站徽标,您可以直接执行该操作,并拥有一个单独的文件/文件夹,其中包含要通过电子邮件发送的实际尺寸,但是为了实时调整大小,您可以尝试这样的操作:

   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电子邮件,并将所有图片调整为我想要的内容