├── .gitignore ├── lib ├── server │ └── pretty-emails.coffee └── templates │ ├── basic.handlebars │ ├── call-to-action.handlebars │ └── shared │ └── footer.handlebars ├── package.js ├── readme.md ├── readme ├── basic.png ├── call-to-action.png └── meteor-pretty-email.png └── versions.json /.gitignore: -------------------------------------------------------------------------------- 1 | .build* 2 | -------------------------------------------------------------------------------- /lib/server/pretty-emails.coffee: -------------------------------------------------------------------------------- 1 | OriginalHandlebars.registerHelper 'footer', -> 2 | options = _.extend(@, PrettyEmail.options) 3 | if options.companyName 4 | Handlebars.templates.footer(options) 5 | 6 | OriginalHandlebars.registerHelper 'eachLine', (content, options) -> 7 | _.reduce content?.split('\n'), (result, content) -> 8 | result + options.fn(content) 9 | , '' 10 | 11 | PrettyEmail = 12 | options: {} 13 | defaults: 14 | verifyEmail: 15 | heading: 'Just one more step...' 16 | message: 'Click on the big button below to activate your account' 17 | buttonText: 'Activate account' 18 | resetPassword: 19 | heading: 'Reset your password' 20 | message: 'Click the big button below to reset your password' 21 | buttonText: 'Reset password' 22 | enrollAccount: 23 | heading: 'To start using service, simply click the button below' 24 | buttonText: 'Change password' 25 | 26 | style: 27 | fontFamily: 'Helvetica' 28 | fontColor: '#606060' 29 | buttonColor: '#FFFFFF' 30 | buttonBgColor: '#3071a9' 31 | 32 | send: (template, options) -> 33 | options = _.extend {}, @options, options 34 | 35 | Email.send 36 | from: options.from 37 | to: options.to 38 | subject: options.subject, 39 | html: @render template, options 40 | render: (template, options) -> 41 | options.style = @style 42 | options = _.extend {}, @options, options 43 | 44 | if typeof template == 'string' 45 | template = Handlebars.templates[template] 46 | 47 | if typeof template == 'function' 48 | template(options) 49 | else 50 | throw new Error "PrettyEmail can't render template. Pass template name or handlebars function." 51 | 52 | Accounts = Package['accounts-base']?.Accounts 53 | 54 | Accounts?.emailTemplates?.verifyEmail.subject = -> 55 | 'Activate your account' 56 | Accounts?.emailTemplates?.verifyEmail.html = (user, verifyEmailUrl) -> 57 | options = _.extend {}, PrettyEmail.defaults.verifyEmail, 58 | subject: Accounts.emailTemplates.verifyEmail.subject(user) 59 | buttonUrl: verifyEmailUrl 60 | PrettyEmail.render 'call-to-action', options 61 | 62 | Accounts?.emailTemplates?.resetPassword.subject = -> 63 | 'Reset your password' 64 | Accounts?.emailTemplates?.resetPassword.html = (user, resetPasswordUrl) -> 65 | options = _.extend {}, PrettyEmail.defaults.resetPassword, 66 | subject: Accounts.emailTemplates.resetPassword.subject(user) 67 | buttonUrl: resetPasswordUrl 68 | PrettyEmail.render 'call-to-action', options 69 | 70 | Accounts?.emailTemplates?.enrollAccount.subject = -> 71 | 'An account has been created for you' 72 | Accounts?.emailTemplates?.enrollAccount.html = (user, enrollAccountUrl) -> 73 | options = _.extend {}, PrettyEmail.defaults.enrollAccount, 74 | subject: Accounts.emailTemplates.enrollAccount.subject(user) 75 | buttonUrl: enrollAccountUrl 76 | PrettyEmail.render 'call-to-action', options 77 | 78 | Meteor.startup -> 79 | if PrettyEmail.options.from 80 | Accounts.emailTemplates.from = PrettyEmail.options.from 81 | -------------------------------------------------------------------------------- /lib/templates/basic.handlebars: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | {{subject}} 9 | 10 | 389 | 390 |
391 | 392 | 393 | 812 | 813 |
394 | 395 | 396 | 397 | 434 | 435 | 436 | 464 | 465 | 466 | 498 | 499 | 500 | 808 | 809 |
398 | 399 | 400 | 401 | 430 | 431 |
402 | 403 | 404 | 427 | 428 | 429 |
405 | 406 | 407 | 408 | 409 | 413 | 414 |
410 | 411 | {{{subject}}} 412 |
415 | 416 | 417 | 418 | 419 | 423 | 424 |
420 | 421 | 422 |
425 | 426 |
432 | 433 |
437 | 438 | 439 | 440 | 460 | 461 |
441 | 442 | 443 | 444 | 457 | 458 | 459 |
445 | 446 | 447 | 454 | 455 |
448 | 449 | {{#if logoUrl}} 450 | 451 | {{/if}} 452 | 453 |
456 |
462 | 463 |
467 | 468 | 469 | 470 | 494 | 495 |
471 | 472 | 473 | 491 | 492 | 493 |
474 | 475 | 476 | 477 | 478 | 487 | 488 |
479 | 480 |

{{{heading}}}

481 | 482 |

{{{headingSmall}}}

483 | 484 | {{#eachLine message}}

{{{this}}}

{{/eachLine}} 485 | 486 |
489 | 490 |
496 | 497 |
501 | 502 | 503 | 504 | {{#if showFollowBlock}} 505 | 804 | 805 |
506 | 507 | 508 | 782 | 783 | 784 |
509 | 510 | 511 | 778 | 779 |
512 | 513 | 514 | 775 | 776 |
515 | 516 | 517 | 771 | 772 |
518 | 519 | 520 | {{#if facebook}} 521 | 522 | 523 | 524 | 527 | 528 | 529 | 530 | 531 | 534 | 535 | 536 |
525 | Facebook 526 |
532 | Facebook 533 |
537 | {{/if}} 538 | 539 | 540 | 544 | 545 | {{#if twitter}} 546 | 547 | 548 | 549 | 552 | 553 | 554 | 555 | 556 | 559 | 560 | 561 |
550 | Twitter 551 |
557 | Twitter 558 |
562 | {{/if}} 563 | 564 | 565 | 569 | 570 | {{#if googlePlus}} 571 | 572 | 573 | 574 | 577 | 578 | 579 | 580 | 581 | 584 | 585 | 586 |
575 | Google Plus 576 |
582 | Google Plus 583 |
587 | {{/if}} 588 | 589 | 590 | 594 | 595 | {{#if instagram}} 596 | 597 | 598 | 599 | 602 | 603 | 604 | 605 | 606 | 609 | 610 | 611 |
600 | Instagram 601 |
607 | Instagram 608 |
612 | {{/if}} 613 | 614 | 615 | 619 | 620 | {{#if pinterest}} 621 | 622 | 623 | 624 | 627 | 628 | 629 | 630 | 631 | 634 | 635 | 636 |
625 | Pinterest 626 |
632 | Pinterest 633 |
637 | {{/if}} 638 | 639 | 640 | 644 | 645 | {{#if youtube}} 646 | 647 | 648 | 649 | 652 | 653 | 654 | 655 | 656 | 659 | 660 | 661 |
650 | YouTube 651 |
657 | YouTube 658 |
662 | {{/if}} 663 | 664 | 665 | 669 | 670 | {{#if linkedin}} 671 | 672 | 673 | 674 | 677 | 678 | 679 | 680 | 681 | 684 | 685 | 686 |
675 | LinkedIn 676 |
682 | LinkedIn 683 |
687 | {{/if}} 688 | 689 | 690 | 694 | 695 | {{#if tumblr}} 696 | 697 | 698 | 699 | 702 | 703 | 704 | 705 | 706 | 709 | 710 | 711 |
700 | Tumblr 701 |
707 | Tumblr 708 |
712 | {{/if}} 713 | 714 | 715 | 719 | 720 | {{#if website}} 721 | 722 | 723 | 724 | 727 | 728 | 729 | 730 | 731 | 734 | 735 | 736 |
725 | Website 726 |
732 | Website 733 |
737 | {{/if}} 738 | 739 | 740 | 744 | 745 | {{#if email}} 746 | 747 | 748 | 749 | 752 | 753 | 754 | 755 | 756 | 759 | 760 | 761 |
750 | Email 751 |
757 | Email 758 |
762 | {{/if}} 763 | 764 | 765 | 769 | 770 |
773 | {{/if}} 774 |
777 |
780 | 781 |
785 | 786 | 787 | 801 | 802 | 803 |
788 | 789 | 790 | 791 | 792 | 797 | 798 |
793 | {{#if showFooter}} 794 | {{{footer}}} 795 | {{/if}} 796 |
799 | 800 |
806 | 807 |
810 | 811 |
814 |
815 | 816 | 817 | -------------------------------------------------------------------------------- /lib/templates/call-to-action.handlebars: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | {{subject}} 9 | 10 | 389 | 390 |
391 | 392 | 393 |
394 | 395 | 396 | 397 | 434 | 435 | 436 | 464 | 465 | 466 | 850 | 851 |
398 | 399 | 400 | 401 | 430 | 431 |
402 | 403 | 404 | 427 | 428 | 429 |
405 | 406 | 407 | 408 | 409 | 413 | 414 |
410 | 411 | {{{subject}}} 412 |
415 | 416 | 417 | 418 | 419 | 423 | 424 |
420 | 421 | 422 |
425 | 426 |
432 | 433 |
437 | 438 | 439 | 440 | 460 | 461 |
441 | 442 | 443 | 444 | 457 | 458 | 459 |
445 | 446 | 447 | 454 | 455 |
448 | 449 | {{#if logoUrl}} 450 | 451 | {{/if}} 452 | 453 |
456 |
462 | 463 |
467 | 468 | 469 | 470 | 536 | 537 | 538 | 846 | 847 |
471 | 472 | 473 | 491 | 492 | 493 |
474 | 475 | 476 | 477 | 478 | 487 | 488 |
479 | 480 |

{{{heading}}}

481 | 482 |

{{{headingSmall}}}

483 | 484 | {{#eachLine message}}

{{{this}}}

{{/eachLine}} 485 | 486 |
489 | 490 |
494 | 495 | 496 | 507 | 508 | 509 |
497 | 498 | 499 | 500 | 503 | 504 | 505 |
501 | {{{buttonText}}} 502 |
506 |
510 | 511 | 512 | 532 | 533 |
513 | 514 | 515 | 529 | 530 | 531 |
516 | 517 | 518 | 519 | 520 | 525 | 526 |
521 | 522 | {{#eachLine messageAfterButton}}

{{{this}}}

{{/eachLine}} 523 | 524 |
527 | 528 |
534 | 535 |
539 | 540 | 541 | 542 | {{#if showFollowBlock}} 543 | 842 | 843 |
544 | 545 | 546 | 820 | 821 | 822 |
547 | 548 | 549 | 816 | 817 |
550 | 551 | 552 | 813 | 814 |
553 | 554 | 555 | 809 | 810 |
556 | 557 | 558 | {{#if facebook}} 559 | 560 | 561 | 562 | 565 | 566 | 567 | 568 | 569 | 572 | 573 | 574 |
563 | Facebook 564 |
570 | Facebook 571 |
575 | {{/if}} 576 | 577 | 578 | 582 | 583 | {{#if twitter}} 584 | 585 | 586 | 587 | 590 | 591 | 592 | 593 | 594 | 597 | 598 | 599 |
588 | Twitter 589 |
595 | Twitter 596 |
600 | {{/if}} 601 | 602 | 603 | 607 | 608 | {{#if googlePlus}} 609 | 610 | 611 | 612 | 615 | 616 | 617 | 618 | 619 | 622 | 623 | 624 |
613 | Google Plus 614 |
620 | Google Plus 621 |
625 | {{/if}} 626 | 627 | 628 | 632 | 633 | {{#if instagram}} 634 | 635 | 636 | 637 | 640 | 641 | 642 | 643 | 644 | 647 | 648 | 649 |
638 | Instagram 639 |
645 | Instagram 646 |
650 | {{/if}} 651 | 652 | 653 | 657 | 658 | {{#if pinterest}} 659 | 660 | 661 | 662 | 665 | 666 | 667 | 668 | 669 | 672 | 673 | 674 |
663 | Pinterest 664 |
670 | Pinterest 671 |
675 | {{/if}} 676 | 677 | 678 | 682 | 683 | {{#if youtube}} 684 | 685 | 686 | 687 | 690 | 691 | 692 | 693 | 694 | 697 | 698 | 699 |
688 | YouTube 689 |
695 | YouTube 696 |
700 | {{/if}} 701 | 702 | 703 | 707 | 708 | {{#if linkedin}} 709 | 710 | 711 | 712 | 715 | 716 | 717 | 718 | 719 | 722 | 723 | 724 |
713 | LinkedIn 714 |
720 | LinkedIn 721 |
725 | {{/if}} 726 | 727 | 728 | 732 | 733 | {{#if tumblr}} 734 | 735 | 736 | 737 | 740 | 741 | 742 | 743 | 744 | 747 | 748 | 749 |
738 | Tumblr 739 |
745 | Tumblr 746 |
750 | {{/if}} 751 | 752 | 753 | 757 | 758 | {{#if website}} 759 | 760 | 761 | 762 | 765 | 766 | 767 | 768 | 769 | 772 | 773 | 774 |
763 | Website 764 |
770 | Website 771 |
775 | {{/if}} 776 | 777 | 778 | 782 | 783 | {{#if email}} 784 | 785 | 786 | 787 | 790 | 791 | 792 | 793 | 794 | 797 | 798 | 799 |
788 | Email 789 |
795 | Email 796 |
800 | {{/if}} 801 | 802 | 803 | 807 | 808 |
811 | {{/if}} 812 |
815 |
818 | 819 |
823 | 824 | 825 | 839 | 840 | 841 |
826 | 827 | 828 | 829 | 830 | 835 | 836 |
831 | {{#if showFooter}} 832 | {{{footer}}} 833 | {{/if}} 834 |
837 | 838 |
844 | 845 |
848 | 849 |
852 | 853 | 854 | 855 | -------------------------------------------------------------------------------- /lib/templates/shared/footer.handlebars: -------------------------------------------------------------------------------- 1 | You are getting this message because you signed up to {{siteName}}, a product managed by {{companyName}}. {{companyAddress}}. {{companyTelephone}} {{companyEmail}} 2 | -------------------------------------------------------------------------------- /package.js: -------------------------------------------------------------------------------- 1 | Package.describe({ 2 | name: "yogiben:pretty-email", 3 | summary: "Send pretty emails", 4 | version: "0.0.7", 5 | git: "https://github.com/yogiben/meteor-pretty-email" 6 | }); 7 | 8 | Package.onUse(function(api) { 9 | api.versionsFrom('METEOR@1.0'); 10 | 11 | api.use('coffeescript'); 12 | api.use('email'); 13 | api.use('underscore'); 14 | api.use([ 15 | 'accounts-base', 16 | 'accounts-password' 17 | ], { weak: true }); 18 | api.use('cmather:handlebars-server@2.0.0'); 19 | 20 | api.addFiles( 21 | [ 22 | 'lib/server/pretty-emails.coffee', 23 | 'lib/templates/shared/footer.handlebars', 24 | 'lib/templates/call-to-action.handlebars', 25 | 'lib/templates/basic.handlebars' 26 | ], 27 | 'server'); 28 | 29 | api.export('PrettyEmail', 'server'); 30 | }); 31 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | Send pretty emails 2 | ================== 3 | 4 | `meteor add yogiben:pretty-email` 5 | 6 | ### What this package does ### 7 | 1. Replaces boring default Meteor emails 8 | 2. Easily send pretty emails with call to action buttons 9 | 10 | ![alt tag](https://raw.githubusercontent.com/yogiben/meteor-pretty-email/master/readme/meteor-pretty-email.png) 11 | 12 | 13 | ### Usage ### 14 | 15 | 1) Install the package 16 | 17 | 2) Set up global options 18 | 19 | e.g. 20 | 21 | ``` 22 | PrettyEmail.options = 23 | from: 'support@mycompany.com' 24 | logoUrl: 'http://mycompany.com/logo.png' 25 | companyName: 'myCompany' 26 | companyUrl: 'http://mycompany.com' 27 | companyAddress: '123 Street, ZipCode, City, Country' 28 | companyTelephone: '+1234567890' 29 | companyEmail: 'support@mycompany.com' 30 | siteName: 'mycompany' 31 | ``` 32 | 33 | 3) Send your emails 34 | 35 | ``` 36 | Accounts.sendVerificationEmail Meteor.userId() 37 | Accounts.sendResetPasswordEmail Meteor.userId() 38 | Accounts.sendEnrollmentEmail Meteor.userId() 39 | ``` 40 | 41 | or using template 42 | 43 | ``` 44 | PrettyEmail.send 'call-to-action', 45 | to: 'myuser@myuser.com' 46 | subject: 'You got new message' 47 | heading: 'Your friend sent you a message' 48 | message: 'Click the button below to read the message' 49 | buttonText: 'Read message' 50 | buttonUrl: 'http://mycompany.com/messages/2314' 51 | messageAfterButton: "I come after the button!" 52 | ``` 53 | 54 | ### Templates ### 55 | 56 | #### Call to action #### 57 | 58 | ![call-to-action](readme/call-to-action.png) 59 | 60 | ``` 61 | PrettyEmail.send 'call-to-action', options 62 | ``` 63 | 64 | **Options** 65 | 66 | ``from`` - required 67 | 68 | ``to`` - required 69 | 70 | ``subject`` - required 71 | 72 | ``heading`` - required. Primary heading 73 | 74 | ``headingSmall`` - optional. Secondary heading 75 | 76 | ``message`` - required. Message to the user (e.g. 'Your bill has been paid') 77 | 78 | ``buttonText`` - required. e.g. 'See your bill' 79 | 80 | ``buttonUrl`` - required. e.g. 'http://mycompany.com/bills/12341234' 81 | 82 | #### Basic #### 83 | 84 | ![basic](readme/basic.png) 85 | 86 | Similar to call-to-action template except that it doesn't have a button and text is not centered. 87 | 88 | **Options** 89 | 90 | ``from`` - required 91 | 92 | ``to`` - required 93 | 94 | ``subject`` - required 95 | 96 | ``heading`` - required. Primary heading 97 | 98 | ``headingSmall`` - optional. Secondary heading 99 | 100 | ``message`` - required. Message to the user (e.g. 'Your bill has been paid') 101 | 102 | ### Global options ### 103 | 104 | You can set your options globally with ``PrettyEmail.options`` object. ``PrettyEmail.send`` will merge this object with options argument so you can put here some other values (e.g. ``from`` ``to`` ``subject``). 105 | 106 | ``showFooter`` - default true 107 | 108 | ``showFollowBlock`` - default true 109 | 110 | ``facebook`` ``twitter`` ``googlePlus`` ``instagram`` ``pinterest`` ``youtube`` ``linkedin`` ``tumblr`` ``website`` ``email`` - links to specific social medias 111 | 112 | ``companyName`` - name of your company (must be specified otherwise footer won't be rendered) 113 | 114 | ``companyUrl`` - url of your company website 115 | 116 | ``companyEmail`` - email of your company 117 | 118 | ``companyAddress`` - address of your company 119 | 120 | ``companyTelephone`` - telephone number of your company 121 | 122 | ``siteName`` - name of your website 123 | 124 | ### Custom style ### 125 | 126 | You can change the style of your emails by manipulating ``PrettyEmail.style`` object. See default values below: 127 | 128 | ``` 129 | PrettyEmail.style = 130 | fontFamily: 'Helvetica' 131 | textColor: '#606060' 132 | buttonColor: '#FFFFFF' 133 | buttonBgColor: '#007FFF' 134 | ``` 135 | 136 | ### Customizing Accounts emails ### 137 | You can change the text in the verification email etc. 138 | 139 | e.g. 140 | 141 | ``` 142 | PrettyEmail.defaults.verifyEmail = 143 | heading: 'Need to activate your account' 144 | buttonText: 'Activate' 145 | ... 146 | ``` 147 | -------------------------------------------------------------------------------- /readme/basic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yogiben/meteor-pretty-email/0c5390b5e43163e43b345cd197fae5d9c7935b7e/readme/basic.png -------------------------------------------------------------------------------- /readme/call-to-action.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yogiben/meteor-pretty-email/0c5390b5e43163e43b345cd197fae5d9c7935b7e/readme/call-to-action.png -------------------------------------------------------------------------------- /readme/meteor-pretty-email.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yogiben/meteor-pretty-email/0c5390b5e43163e43b345cd197fae5d9c7935b7e/readme/meteor-pretty-email.png -------------------------------------------------------------------------------- /versions.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": [ 3 | [ 4 | "accounts-base", 5 | "1.1.2" 6 | ], 7 | [ 8 | "accounts-password", 9 | "1.0.4" 10 | ], 11 | [ 12 | "application-configuration", 13 | "1.0.3" 14 | ], 15 | [ 16 | "base64", 17 | "1.0.1" 18 | ], 19 | [ 20 | "binary-heap", 21 | "1.0.1" 22 | ], 23 | [ 24 | "callback-hook", 25 | "1.0.1" 26 | ], 27 | [ 28 | "check", 29 | "1.0.2" 30 | ], 31 | [ 32 | "cmather:handlebars-server", 33 | "0.2.0" 34 | ], 35 | [ 36 | "coffeescript", 37 | "1.0.4" 38 | ], 39 | [ 40 | "ddp", 41 | "1.0.11" 42 | ], 43 | [ 44 | "ejson", 45 | "1.0.4" 46 | ], 47 | [ 48 | "email", 49 | "1.0.4" 50 | ], 51 | [ 52 | "follower-livedata", 53 | "1.0.2" 54 | ], 55 | [ 56 | "geojson-utils", 57 | "1.0.1" 58 | ], 59 | [ 60 | "handlebars", 61 | "1.0.1" 62 | ], 63 | [ 64 | "id-map", 65 | "1.0.1" 66 | ], 67 | [ 68 | "json", 69 | "1.0.1" 70 | ], 71 | [ 72 | "localstorage", 73 | "1.0.1" 74 | ], 75 | [ 76 | "logging", 77 | "1.0.5" 78 | ], 79 | [ 80 | "meteor", 81 | "1.1.3" 82 | ], 83 | [ 84 | "minimongo", 85 | "1.0.5" 86 | ], 87 | [ 88 | "mongo", 89 | "1.0.8" 90 | ], 91 | [ 92 | "npm-bcrypt", 93 | "0.7.7" 94 | ], 95 | [ 96 | "ordered-dict", 97 | "1.0.1" 98 | ], 99 | [ 100 | "random", 101 | "1.0.1" 102 | ], 103 | [ 104 | "retry", 105 | "1.0.1" 106 | ], 107 | [ 108 | "service-configuration", 109 | "1.0.2" 110 | ], 111 | [ 112 | "sha", 113 | "1.0.1" 114 | ], 115 | [ 116 | "srp", 117 | "1.0.1" 118 | ], 119 | [ 120 | "tracker", 121 | "1.0.3" 122 | ], 123 | [ 124 | "underscore", 125 | "1.0.1" 126 | ] 127 | ], 128 | "pluginDependencies": [], 129 | "toolVersion": "meteor-tool@1.0.35", 130 | "format": "1.0" 131 | } --------------------------------------------------------------------------------