2016-06-10 1 views
0

나는 grails 프로젝트에서 이메일 뷰를 정리하려고한다. 우리 팀은 모든 이메일에 대해 동일한 소개, 로고 및 사인을 사용합니다. 나는 이것을 전통적인 grails 레이아웃 파일에 넣으려고하고 <meta name="layout" content="email"/> 메타 태그로 호출하려고 시도했지만 작동하지 않는 것 같습니다. 이 이메일 템플릿을위한 단 하나의 레이아웃을 만들 수있는 또 다른 방법이 있습니까?Grails 이메일의 DRY 레이아웃?

+0

이것은 작동하지 않습니다. 이메일 템플리트 내에서 이미지 ID 태그와 일치하는 인라인 이미지 첨부 파일을 조사해야합니다. 여러 이미지 = 여러 개의 인라인 첨부 파일 – Vahid

답변

0

DRY로 무엇을 의미하는지 알아 내려고했는데, 루비 용어 라야한다고 생각합니다. 템플릿이라고 생각합니다.

HTML 전자 메일의 문제점은 실제로 로고 (머리글/바닥 글)를 포함 할 때 모든 언어의 표준 문제입니다. 표준이 다양하고 일부 메일 클라이언트에서 작동하는 동안 예를 들어 웹 메일 (예 : 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 콘텐츠 형식과 실제 파일 이름을 containts 경우 나는 목록을 가지고 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는 템플릿을 사용하여 같이 일할 것이라고 생각 비트는 대신 원하는 것을하지 않습니다 당신이 할 수있는 상기와 그것이 템플릿을 렌더링하고있는 것을 보아라. 그러나 템플릿은 html 페이지에 가득 차있는 전형적인 gsp 템플릿이다 :

당신은 HTML 이메일로 주요 문제는 CSS 스타일이 매우 잘 작동하지 않는다는 것입니다 볼
<%@ 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> 

, 그것은 어떤 경우에는 그러나 많은 경우에 작동


/이메일/emailTemplate를 사용하면 더 나은 기존 테이블을 고수하고 스타일 태그를 사용하여 레이아웃을 올바르게 선언합니다.

이 과정이 진행되는 동안 실제 사이트 CSS 파일을 사용하는 것을 잊어 버리십시오. 직접 이메일을 생성하여 전송하기 때문입니다. 사이트 CSS 파일에 대한 인식이 없습니다. 여러 이미지에 관해서

우리는 여기에 대해

사용자의 목록입니다 이야기

USERA {USERA 사진}/사용자 A 설명 사용자 B {사용자 B 사진}/사용자 B의 설명 위의

솔루션에는 필요한 모든 인라인 이미지를 추가하는 데 필요한 모든 것이 있습니다. 즉 이메일에 이미지를 첨부하고 있다는 의미이므로 이미지가 거대하면 이미지를 다시 포맷하고 크기를 조정하기 위해 이미지를 첨부합니다.

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 [:] 
    } 

: 당신의 자신의 위치에 대한

당신이 뭔가를 시도 할 수-크기 다시 비행에 직접 그렇게 실제 크기가 이메일로 전송을 포함하는 별도의 파일/폴더가 있지만위한 수 있습니다 로고를 이것은 지금은 위의 이미지 매핑을 수행 할 때까지 매핑이 내가 필요한 모든가 크기를 조정할만큼의 이미지와 함께 HTML 이메일을 달성하기 위해 통과했다 두통을 많이 웁니다

def res = PhotosBean.getPhoto(ui.attributes.profilePhoto) 
          if (res) { 
           images << [id: "uImage${ui.id}", contentType: "${res.contentType}", file: res.file] 
          } 

희망 내가 원하는 번호 :

+0

DRY는 "Do not Repeat Yourself"의 약자로, 두 곳에서 동일한 코드를 사용하지 않으려는 깨끗한 코드 교리입니다. – billjamesdev

+0

https://github.com/vahidhedayati/grails-bean-validation-examples에는 위의 코드가 모두 포함 된 매우 복잡한 이미지 bean이 포함되어 있습니다. https://www.youtube.com/watch?v=ATLQ7CCvPvI 여기에 설명되어 있으며 귀하가 습득하려고 시도한 내용을 다루고 있습니다. Whist this with this example 프로젝트의 일부로 포함 된 복잡한 이미징 메커니즘이 있다는 것을 깨달았다. https://github.com/vahidhedayati/grails-bean-validation-examples/tree/master/src/main/groovy/ org/imgscalr – Vahid