PageSourceSearch

https://cromwellcms.com/assets/js/532e6e91.1ae7e912.js

js cromwellcms.com collected 2026-10-04 13:34:02 UTC 7,575 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunk_cromwell_website=self.webpackChunk_cromwell_website||[]).push([[9542],{1490:function(e,t,r){r.r(t),r.d(t,{frontMatter:function(){return s},contentTitle:function(){return l},metadata:function(){return p},toc:function(){return m},default:function(){return c}});var n=r(5773),a=r(808),i=(r(7378),r(5318)),o=["components"],s={sidebar_position:1},l="Mail",p={unversionedId:"features/mail",id:"features/mail",isDocsHomePage:!1,title:"Mail",description:"Emailing is a required feature of every CMS for sending transactional e-mails such as password resets, order placements, etc.",source:"@site/docs/features/mail.md",sourceDirName:"features",slug:"/features/mail",permalink:"/docs/features/mail",tags:[],version:"current",sidebarPosition:1,frontMatter:{sidebar_position:1},sidebar:"tutorialSidebar",previous:{title:"Overview",permalink:"/docs/features/overview"},next:{title:"Migration",permalink:"/docs/features/migration"}},m=[{value:"Templates",id:"templates",children:[]}],u={toc:m};function c(e){var t=e.components,r=(0,a.Z)(e,o);return(0,i.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h1",{id:"mail"},"Mail"),(0,i.kt)("p",null,"Emailing is a required feature of every CMS for sending transactional e-mails such as password resets, order placements, etc.",(0,i.kt)("br",{parentName:"p"}),"\n","By default, Cromwell CMS sends emails with resources of ",(0,i.kt)("a",{parentName:"p",href:"https://www.npmjs.com/package/sendmail"},"Node.js server"),'. But often you may notice that messages end up in a "spam" folder or never reach an address. That usually happens with self-hosted servers because email service providers don\'t trust them without proper configuration.'),(0,i.kt)("p",null,"To fix the situation Cromwell CMS provides integration with SMTP service providers. You can choose a provider dependent on your needs or preferences, for integration to work you have to provide a ",(0,i.kt)("a",{parentName:"p",href:"https://nodemailer.com/smtp/"},"connection string")," in the form: ",(0,i.kt)("inlineCode",{parentName:"p"},"smtps://username:[email protected]"),"  "),(0,i.kt)("p",null,"We do not promote any provider, but just for the sake of example, there is a short instruction on how to set up ",(0,i.kt)("a",{parentName:"p",href:"https://sendgrid.com/"},"Sendgrid"),".  "),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://signup.sendgrid.com/"},"Create an account")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://app.sendgrid.com/settings/sender_auth/senders/new"},"Create a new sender")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://app.sendgrid.com/guide/integrate/langs/smtp"},"Create API key")," "),(0,i.kt)("li",{parentName:"ul"},"Create a connection string with your key: ",(0,i.kt)("inlineCode",{parentName:"li"},"smtps://apikey:[email protected]"),", so it will look like: ",(0,i.kt)("inlineCode",{parentName:"li"},"smtps://apikey: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@smtp.sendgrid.net")),(0,i.kt)("li",{parentName:"ul"},'Go to the Admin panel > Settings page > Emailing settings. In "Send e-mails from" paste the e-mail address you submitted for a Sendgrid sender in the field "From Email Address". Paste your connection string in the field below.')),(0,i.kt)("h2",{id:"templates"},"Templates"),(0,i.kt)("p",null,"Emailing templates can be fully customized for your website.",(0,i.kt)("br",{parentName:"p"}),"\n","Navigate to ",(0,i.kt)("a",{parentName:"p",href:"/docs/overview/installation#working-directories"},(0,i.kt)("inlineCode",{parentName:"a"},".cromwell/server/emails"))," directory. There are copied number of templates:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"order.hbs")," - For new order placement"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"forgot-password.hbs")," - Email with secret code when user starts reset-password transaction.")),(0,i.kt)("p",null,"The CMS uses ",(0,i.kt)("a",{parentName:"p",href:"https://handlebarsjs.com/guide/"},"Handlebars")," as templating engine. You can edit CMS templates as you like, just keep Handlebars variables to insert data."),(0,i.kt)("div",{className:"admonition admonition-important alert alert--info"}
1,(0,i.kt)("div",{parentName:"div",className:"admonition-heading"},(0,i.kt)("h5",{parentName:"div"},(0,i.kt)("span",{parentName:"h5",className:"admonition-icon"},(0,i.kt)("svg",{parentName:"span",xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"},(0,i.kt)("path",{parentName:"svg",fillRule:"evenodd",d:"M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"}))),"important")),(0,i.kt)("div",{parentName:"div",className:"admonition-content"},(0,i.kt)("p",{parentName:"div"},"Make a backup of your custom template. When you run CMS update, it may possibly replace your templates with new ones. Your templates may become incompatible if some variables change in original template. Even though we'll try not to change them or do that as less as possible, this possibility still exists for now. In the future, we'll work out more convenient way for such updates."))))}c.isMDXComponent=!0},5318:function(e,t,r){r.d(t,{Zo:function(){return m},kt:function(){return d}});var n=r(7378);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function o(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?i(Object(r),!0).forEach((function(t){a(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):i(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function s(e,t){if(null==e)return{};var r,n,a=function(e,t){if(null==e)return{};var r,n,a={},i=Object.keys(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var l=n.createContext({}),p=function(e){var t=n.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):o(o({},t),e)),r},m=function(e){var t=p(e.components);return n.createElement(l.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},c=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,i=e.originalType,l=e.parentName,m=s(e,["components","mdxType","originalType","parentName"]),c=p(r),d=a,f=c["".concat(l,".").concat(d)]||c[d]||u[d]||i;return r?n.createElement(f,o(o({ref:t},m),{},{components:r})):n.createElement(f,o({ref:t},m))}));function d(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=r.length,o=new Array(i);o[0]=c;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s.mdxType="string"==typeof e?e:a,o[1]=s;for(var p=2;p<i;p++)o[p]=r[p];return n.createElement.apply(null,o)}return n.createElement.apply(null,r)}c.displayName="MDXCreateElement"}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.