Search code examples
htmlcssangularemailgmail

How to display emails in an angular app like it gets displayed in an email client


I am currently trying to develop a web app to display EMails to the user. It is important for me that the emails get displayed like they get in an email client (e.g. gmail). I use the gmail api to import emails to my database then I get the messageparts from the emails into my angular app. The problem is that I am not able to display html emails with the propert styling. It seems like html tags get used correclty but the original styling seems to be lost

I am using angular 7, and spring boot. To collect the Emails I use the gmail api and import them into a postgresql database. I tried to use iframes so my app styling doesn't get in the way of the email styling but it gets displayed the same way.

How I prepare the emails

private String getMessageContent(Message message) {
        StringBuilder stringBuilder = new StringBuilder();
        try {
            if(message.getPayload().getParts() != null) {
                handleEmailMainContent(message.getPayload().getParts(), stringBuilder);
                byte[] bodyBytes = Base64.decodeBase64(stringBuilder.toString());
                return new String(bodyBytes, "UTF-8");
            } else {
                return "";
            }
        } catch (UnsupportedEncodingException e) {
           System.out.println("UnsupportedEncoding: " + e.toString());
            return message.getSnippet();
        }
    }

    private void handleEmailMainContent(List<MessagePart> messageParts, StringBuilder stringBuilder) {
        for (MessagePart messagePart : messageParts) {
            switch (messagePart.getMimeType()) {
                case "text/plain":
                    handleMimeTypeTextPlain(messagePart, stringBuilder);
                    break;
                case "text/html":
                    handleMimeTypeTextHtml(messagePart, stringBuilder);
                    break;
                default:
                    break;
            }
        }
    }

Note: selectedEmail.mainContent is the String I build above

Example

The content inside mainContent are phishing emails I try to collect and display. The example is a html email I try to display. I ommited the links and most of the spam content.

---------- Forwarded message --------- Von: emailaddress Date: Fr., 10. Mai 2019 um 22:06 Uhr Subject: Name, Give mom the gifts she wants To: emailaddress

image Become part of the Heally family on Facebook link ! - LET'S TALK Celebraing Mom ... Moms run the world. They literally give us life, take on one of the hardest roles, and do it all without an end to their workday or any time off. While moms deserve to be celebrated year-round, Mother’s Day is a special time to make sure they know they’re loved and appreciated. LEARN MORE link

Looking for CBD only Products? PROMO CODE: SAVECBD20 link CBD 20% OFF link Give mom gifts that she actually wants. Shop the Marketplace

-ommited SPAM-

You are receiving this email because you or your medical provider have registered for a Heally account. Unsubscribe link Copyright (C) 2019 Heally Inc. All rights reserved. Unsubscribe

own Example

I tried to send a minimalistic html email to myself containing this content:

*dummy*
<div dir="ltr"><i>dummy</i></div>

and it worked just fine. Maybe the problem is an external class which does not get displayed/loaded and/or not exported by the gmail api

How I tried to display it

<mat-card>
  <mat-card-title>
    Current Email
  </mat-card-title>
  <mat-card-content [innerHTML]="selectedEmail.mainContent">
  </mat-card-content>
</mat-card>

I want to display emails like they get displayed in gmail instead I was only able to display plain text and basic styling through html tags. I don't understand at which of my steps the styling gets lost or if I do not correctly display the emails.


Solution

  • Angular security Blocks dynamic rendering of HTML and other scripts. You need to bypass them using DOM Sanitizer.

    Read more here : Angular Security

    DO below changes in your code :

        // in your component.ts file
    
        //import this 
        import { DomSanitizer } from '@angular/platform-browser';
    
        export class TestComponent{
    
        public htmlData :any ; 
        // in constructor create object 
    
        constructor( 
        ...
        private sanitizer: DomSanitizer
    
        ...
        ){
    
        }
    
        someMethod(){
    
          /* this method must be called after getting the value of selectedEmail.mainContent 
       from service  */
    
    
         this.htmlData = this.sanitizer.bypassSecurityTrustHtml(selectedEmail.mainContent); // this line bypasses angular security
        }
    }
    

    And in compoenent.html

    <div [innerHtml]="htmlData"> </div>
    

    Here is the working StackBlitz : Working Demo