Introduction to Customizing Email Delivery
00:00:07
Speaker
All right, welcome back to another episode of Overengineered, the podcast where we ask the very important question, what's the best way to do things that don't particularly matter? I am back with my friends Skyler and Bogdan, and today we are talking about
00:00:24
Speaker
customizing the way you send email from your application. So everything from how do you change the email recipient and how do you change the content, how do you make the content previewable, and potentially how do you even change the logic behind when and if content gets sent.
Challenges in Email Delivery and Solutions
00:00:50
Speaker
And I think this is something that, you know, we've bumped into in various different ways. And some of it we've sort of been talking about. Well, in the future, we see a case where it's going to get even more complicated than it is. But so far, I think we have a pretty solid solution for one one one piece of this puzzle. But it definitely falls into that category of
00:01:18
Speaker
things that you just kind of run into in different ways and sort of solve-ish and move on. And so I'm excited to try to think of a better way to approach this. But before we get going, I feel like we've each approached this problem in past projects differently. So I think it just be kind of interesting to talk about those experiences and then move from there.
Managing Email Delivery with Vacation Modes and Permissions
00:01:47
Speaker
I mean, I think we, one, one thing that, um, that I've experienced before is, you know, we had a situation where a person was getting reports, uh, from our system like new user activation reports and they were going on leave for over a month and someone else needed to get this email. Um, and also the person that was going on leave, like they didn't need these emails when they got back, they don't need.
00:02:14
Speaker
daily active user reports from a month ago. And so we were like, I guess we'll just like have to remember to deploy a change to the configuration of who gets this email. You know, like it would have been great to have some sort of vacation mode, like from the UI where they could just turn off the email.
00:02:33
Speaker
Um, and someone else could turn it on or activate it. Um, right. Or even be able to like set vacation mode and just enter in the, the, like, who should receive this while I'm gone. That would be pretty cool. Yeah. And, uh, we never liked, I never built that, but it would have been, it would have been a great, uh, a great thing to build. I have built a system to like customize what the email says when it goes out, but I think Bogdan has as well, if you want to chat about your solution there.
00:03:02
Speaker
Yeah, I mean, so going to the first point about kind of how do we manage or keep, you know, like a custom recipient list of who the emails goes to. I think like one of the ways that obviously that we will try it is, you know, or you write some dirty email in a text file, and you read from that text file, and that's your first iteration. But you know, one of the ways that I was able to manage to solve it was
00:03:34
Speaker
the emails that are going out to like a specific permission. So for example, like in your case, Kyler, maybe there's a permission that says like receives new user alerts, right? And let's say you assign 10 people to that permission and all you would have to do is when the email is getting queued up and say, hey, give me all of the people who have those permissions and then you can just send out those people the email itself.
00:03:56
Speaker
you know, I would tie
00:04:02
Speaker
And one of the benefits of that is that if someone ends up leaving the team or maybe temporary leave, you could either deactivate their account, remove that permission. There's multiple ways of kind of like, well, this person's gone for a month. They may not even have access to the system. And that's one way to manage it. And it kind of falls in nicely, whereas you could just say, well, I just want to deactivate this person and whatever
00:04:31
Speaker
permissions they have, whatever emails they have, they would be getting. They would just simply be gone from them. It's like a nice fell swoop.
Customizing Email Content with Templates
00:04:42
Speaker
To the second point about the email customization of the content, one of the ways I did it was, this was early on and I feel like I didn't have a really good concept in email templating engines, maybe mustaches like one of them that we could talk about later.
00:05:00
Speaker
But, you know, I basically adopted like a pretty, you know, I guess, pretty was the word I'm looking for. I don't know, simple, straight forward. Yeah.
00:05:17
Speaker
Nomadic or I don't know, just like very crude version of here's a variable in a template and we're just going to replace it with some sort of variable that comes from like a PHP file. So it wasn't anything that could actually provide like logic like hey, if this is set then show this or here's a list of items. It was just like a pretty basic search and replace effectively. So you know, I always felt like that solution was
00:05:46
Speaker
very developer intensive. I was the only one who was able to really configure this stuff, even though there was a UI element where you could write the HTML and you could write the HTML itself and see an instant preview. But I always felt that for the end user, it was super technical. And it was almost like, I think, towards the end of working with those email templates.
00:06:14
Speaker
I actually converted everything into PHP back into Blade templates or Markdown because I would be customizing that stuff anyway. Rather than giving some sort of choice of email templates, I just said, well, there is no choice. This is all you get because it ended up being a little bit of a headache, to be honest.
00:06:36
Speaker
But yeah, so that's kind of like the two approaches for customizing the recipient list or kind of controlling that. And how do you customize the content of the email itself that I've kind of run into? Yeah, listening to this, I actually think there's sort of four pieces that have come up in various ways for us. The sort of three that I already talked about.
00:07:00
Speaker
But also, there's this fourth piece of how do you let non-technical users on your team preview emails, even if they can't edit them. But, you know, if you're just talking about a traditional Laravel mailable,
00:07:20
Speaker
That's going to need to, you know, it's going to accept some real arguments that are often models or other, you know, relatively complex data structures.
Improving Email Configuration Flexibility
00:07:31
Speaker
There's potentially going to be some real logic in there to determine
00:07:36
Speaker
either at the view level, like some conditionals about what parts of the message are being shown depending on the data, or even just like in the mailable itself determining which view it's gonna render. And so even just this question of,
00:07:58
Speaker
You know, this came up for us pretty recently. A staff member was just like, I want to see like what new members receive.
00:08:08
Speaker
it's not like you can just grab that blade template and render it, right? There needs to be a step ahead of there where you're sort of creating some test data and maybe even multiple sets of preview data for a given mailable to account for the different sort of scenarios that
00:08:33
Speaker
a person might receive that in, or if you really wanted to go over the top, give the staff member a way to, almost like, have either of you used, oh gosh, what's it called, a storybook for React? Where you can preview different stories of components, and the way that works is,
00:09:00
Speaker
the different inputs to those components are wired up to these tools that Storybook provides so that the user of Storybook can just enter a name in a box and see how that'll look, or toggle a switch to set a Boolean true or false.
00:09:23
Speaker
you know, that's talk about over engineering, like that's certainly over engineering, but I could imagine a world where that would be very cool, you know, to be able to just say like, okay, this mailable takes these values and let the end user just plug them in, you know, here are the defaults.
00:09:45
Speaker
But yeah, I would say the part of this that I think we have a pretty solid solution for is who receives what, right? So, you know, in the early days, all of these sort of staff reports, you know, new user report or something like that, would just have the recipient hard coded in the message, in the mailable class. Or, you know, maybe, you know, we were just hard coding the recipient in the like,
00:10:14
Speaker
mail to and then we just put in a staff email address and then new user report mail. And obviously that started to feel fragile pretty quickly and like we switched to this concept of like recipient groups where there was a config file and you could go into the config file and there were different named recipient groups and you could add or remove different
00:10:43
Speaker
different folks to different groups so that these three people want to get this mail and these two people want to get that mail. But again, it's what Skyler was saying at the beginning, every time we needed to change who received what, that's a whole deploy. And that's not the end of the world, it's fine, but it got annoying.
00:11:05
Speaker
And so we implemented, I think, Bogdan, you implemented this, right? Configurable? Yeah. So, well, go ahead. Why don't you talk about how configurable recipients works right now in our app?
00:11:20
Speaker
Sure. So I think like one of the main challenges that we had to solve early on was the actual like admin UI, right? And I'll kind of step for that from that perspective first. And one of the ways we kind of do this, we just say we just query, we just kind of search for all of the files that are extending like a mailable class. And we're talking about a layerable project here.
00:11:42
Speaker
And we basically presented on like an index page for the administrator to kind of control or to see which mailables are configurable. And we allowed the administrator to go in and select a user or multiple users who receive this mail.
00:12:07
Speaker
And then when the email is actually sent, all we're doing is matching the class name of that mailable to all the recipients that are configured for that mailable. And that's how we're able to control from a non-deployment side, from a UI who is getting what
Enhancing Email Management Features
00:12:31
Speaker
Um, so I think like it has been working fairly well for us. I think there's a few small, uh, things that, um, you know, still need to be ironed out in terms of, um, one of the things that Skylar mentioned, for example, like
00:12:46
Speaker
a vacation mode or if somebody is leaving or someone else needs to get these emails like we sometimes forget to go in there and change the recipients. Even though it's easy, I still feel like we're sending some emails to people who shouldn't be or vice versa.
00:13:06
Speaker
So I think there still could be some improvement. But overall, I think it's a major leap forward than deploying email address changes instead.
00:13:21
Speaker
Yeah, I mean, I could see pretty easily adding some concept of like recipient groups, right? Where, you know, kind of like what we were doing before with these arrays, there could be a billing group and this is, you know, that's folks who receive billing related emails, right? And there's like, I don't know, like tech support group or whatever, right? And that's people who receive tech support type emails.
00:13:47
Speaker
And then instead of having to go and look through the different messages that are being sent and decide like, where do I add this person or where do I need to go to remove this person? It would be like you could add or remove a single user to a single email if that makes sense, but you could also add or remove
00:14:08
Speaker
a user to a recipient group and then any message that goes to that group would also go to that user. I think that could be a nice addition. Yeah, I think it compliments what I was mentioning earlier. You could have some group or permission that a user is assigned to, and then that way, we're just fetching data from that. We're fetching the users based on that rule or that permission or group.
00:14:36
Speaker
Uh, it's a little bit more flexible almost, you know, where you could be like, well, here's 10 people in this group. They all get these emails. Um, yeah. One thing that, one thing that this also kind of helps all for is like, um, you know, at a previous job, we had multiple staging environments that were connected up to real. Send good credentials. Cause we wanted to make sure like things were actually being sent and, but we were like hard coding emails, email addresses in. So then like.
00:15:06
Speaker
you know, our billing manager was getting these emails from staging data and being like, um, I can't set up this account, like one, two, three main street, like what city, like what, like, so then, so then in our email templates, we had to be like, if environment, not production, like add this huge red block that just said like staging environment, like you can disregard and like that's, it was just kind of gross. And so being able to,
00:15:31
Speaker
And so some of the emails, we would store the email addresses in our environment file. New recipient email address. And that stuff just floods up your environment file with all these emails and then not everyone on the dev team has access to the environment.
Simplifying Email Customization and Previewing
00:15:51
Speaker
rightly so. So then like, you know, your lead developer or your DevOps person has to go into the environment and update the config when someone on the support team leaves the company and but it's just it's such a mess. And so this approach where you add a trait to the mail and then we're using reflection to just like find all of the mailables that have that trait and
00:16:16
Speaker
let that then be powered by the database. It was a very cool feature to see. Yeah, and just to be clear, I mean, how this works, Bogdan's right, probably the hardest part of this feature was, you know, essentially,
00:16:35
Speaker
making the index page that shows all of the mailables that implement this trait, that use this trait. But with that out of the way, really all this feature is, is just a table that has one column that is the fully qualified class name of the mailable and one column that is the recipient. And in our case,
00:16:59
Speaker
It actually has three columns. You can either configure an email address directly or you can point to a user. And that way if the user changes their email address, they continue to receive any mail that's configured for them. But if something needs to go out to someone who doesn't have a user account, we still handle that scenario.
00:17:25
Speaker
But, you know, the actual technical implementation is not that hard, but it definitely was a huge quality of life improvement. And I think I can imagine sort of a similar approach to some of these other problems where, you know, potentially a mailable right now could essentially pull in like a,
00:17:53
Speaker
you know, has preview states or maybe that would be an interface or something like that, right? And then you just implement like a public static function that's like get preview states. And that just returns an array that's keyed by like the name, like a label or something like that.
00:18:13
Speaker
and then the value is just an instance of the mailable with all of the data that the mailable needs set up, right? And in there, because we could just be loading that in the moment of preview,
00:18:32
Speaker
those objects don't actually have to exist in the database, right? You can just new up some temporary models, you know, do like a factory make instead of a factory create and just set the data that your mailable cares about.
00:18:48
Speaker
And then if there's like a major conditional where someone wants to see both cases, like you just return two different options, one where the condition was true and one where the condition was false. And obviously for more complex logic, setting that up would be a little bit annoying because you might have to set like three or four nested relationships perhaps.
00:19:10
Speaker
And I can see the drift would probably get also to be a problem because realistically, you're going to forget to update those when you update the email contents.
00:19:27
Speaker
But all said, I can see that being a pretty good solution to the preview concept. And then you just do the exact same thing. You just use reflection to find all the mailables that implement this interface and list them. And then when you click on one, it just loads up the state and just renders it. Could you just use reflection on all of the mailables
00:19:56
Speaker
infer the parameters. And like, oh, it's a model. Just do like a in random order first model and return it. And or like, if it's a Boolean, just return true or something like we like you could just potentially use reflection to dynamically generate all of this stuff.
00:20:24
Speaker
And maybe there's a way to override it. Like there's a, oh, if you have like preview data, uh, set, then you can use that to kind of like help prevent some of the drift that can happen when you forget to change something. Yeah, that's smart because I, you know, my initial reaction was like, that's great for models and strings and bullions. Um,
00:20:49
Speaker
but like if you're passing in sort of like a DTO or some more complex like custom data structure that's gonna fail, but as long as you have a way to like provide that and you could even, you could even instead of like returning the whole mailable, you could just like
00:21:12
Speaker
almost think of it as like a data provider in testing where you're just returning the argument name and value and that way you're just providing the default that we're just matching back to the name of the argument through reflection and that way
00:21:32
Speaker
Yeah, even if the, the mailable changes, if you only need to customize one of the objects that it receives, like then you're, you're mitigating that even further. I like that a lot. Well, I'm like so much, like I would probably say like 80% of mailables have like a user and like maybe another model.
00:21:58
Speaker
You've got that 20% that has a special DTO and is doing some extra stuff, but so many mailables are just like, who's the user that's going to? And it's like, hi, Bogdan. Your account was past due.
00:22:14
Speaker
And like maybe there's a subscription model that's being passed in, but like there's not so much stuff. It seems like you could just kind of use reflection and then have that extra space, extra function for the 20%. Right, and even like have some heuristics where it's like, you know, if the argument is sense, right, we know that that's like a money amount and so like maybe
00:22:41
Speaker
give some reasonable value. And like, if it receives like a user and a subscription, maybe we find a user and then pass in that user's active subscription because like, I could see if you're just like, if something takes a user, a company and a subscription and you're just passing in
00:23:01
Speaker
like a random one of each of those, there's a good chance that like the mailable is going to blow up because it's assuming that they are related when they're not. Usually that's probably not a problem because they're going to be loaded through relationships anyway. You could always like make a test that says like mail can be previewed and it loops through all of your mailables and like call some render preview button method that
00:23:28
Speaker
we provide and that way, like if something breaks because you've changed, like that would prevent some amount of drift or like some special thing. It's like, oh, the defaults don't work here. I've got to go in and, uh, you know, configure the, the preview data. Yeah. I mean, my only hesitation here is, um, this, this is, uh, this is reminding me of that time. This is pre Skyler, but when, um,
00:23:58
Speaker
Daniel wrote this whole thing that lets you preview all the blade components, being like, well, if we could just see all the blade components, we'd actually use them more and we'd know how they look and how they work. And that whole thing got into production and no one has looked at it since.
00:24:20
Speaker
I did look at it in the first week I was here. And then I was like, all right, cool. And now I've probably stopped looking at it. OK, well, there you go. I think as far as the component preview stuff that Daniel has worked on, I think
00:24:35
Speaker
One of the things I was trying to solve, it was great, like Skyler said, to get up and going seeing what's in the system. But once you're working with this code all the time, you are familiar with all of the components and you just feel more comfortable.
00:24:53
Speaker
Whereas the mailable stuff is a bit hidden. For us, it may be obvious, even though sometimes it's hard to figure out which e-mails exist. But I think for staff particularly, which I feel like most of the requests come from, they want to be able to figure out how an e-mail looks like that is sent to a user. One of the ways they do that right now,
00:25:22
Speaker
is someone replies to them with that email. And they're like, oh, well, that's how that looks like.
Email Content Auditing and Storage Solutions
00:25:28
Speaker
We don't have a really good story for our staff members to actually see what those emails look like when they go out. Obviously, we try to make sure that the text that we put in there is something we all agree on. But I think ultimately, once we deploy that mailable, nobody has any idea really what the final look and feel is.
00:25:52
Speaker
You know, sometimes we try to do good at that, but I think overall like people forget and you know, you just Even if you showed a screenshot of it, you know two months later and no one's gonna remember how it looked like so I think I think it's a little different than having a useless component preview. I think it's valuable to have You know this mailable preview Yeah, it's just a question if if people use it or not
00:26:19
Speaker
You know, I came across a package the other day that has been archived on, on GitHub as like no longer maintained, but it would store a copy of the email content as it was being sent to the individual user. Uh, and it, the purpose of that was that it would inject a view and browser link
00:26:43
Speaker
so that if you didn't want to read the email in your email, you could read it in the browser. But it was just like per user, it was storing this in the database. And it kind of came up
00:26:58
Speaker
where someone on staff was like, what did the email say for this particular customer who like their account was past due, but they were still in a grace period. But I don't actually think they were still in a grace period, but they said that the email had this information. And so kind of the ability to store like, what did, what did this user get at this time? Like, what was the email copy when they got it versus like, Oh, like we changed the email copy
00:27:26
Speaker
And now two weeks ago, it said something different and, you know, it's kind of interesting approach to like store the actual email content and not just, you know, not just data about like opens in and clicks. Yeah. I mean, I personally think that's a really good idea to do that for like auditing purposes. Uh, cause yes, templates do change and you know, uh, that mailable that we created six months ago had text updated.
00:27:56
Speaker
a week ago and nobody was notified and i think it's a good idea to store a copy of that content. Yeah i mean maybe that's even a better solution like if we were to send a bunch of emails to people.
00:28:11
Speaker
And we had the content of those emails. And maybe the previews are just a single email that we randomly select that was sent within the last week. And that's how emails look like. And rather than creating this interface or some trait that you would have to create a random model and random data, maybe that's an easier solution.
00:28:40
Speaker
Yeah. And you could even just like just prune the data. Um, so that there's only say a hundred copies of any given mailable or, you know, whatever the, the threshold that we want. I mean, I'm generally, I have generally become a believer and just keep all the data all the time because there've been so many times that have been burned by not having, uh, something to refer back to, but
00:29:08
Speaker
the contents of every email message that we send out is maybe a lot. But I do think having that for auditing, when you think about it from an auditing perspective, it's useful to be able to go back further. But just from a debugging and previewing perspective, as long as you have a couple even, 10 or whatever copies of any given message,
00:29:35
Speaker
Um, then yeah, for someone who wants to see like, Oh, what does this message look like? They could click through to that mailable and then essentially just have a dropdown list of, you know, the last 30 or last 10 or last hundred, who cares, right? Copies of that message. And they could just, you know, tick through those to take a look at it. Um, and then so long as we're keeping them, you know, maybe we keep them around rather than keeping
00:30:04
Speaker
some set number, maybe we keep them around for two weeks or something like that, or four weeks or something like that. That way, you know, if a staff member is in that situation where it's like, well, what did this email, like I would just talk to someone who said they got an email yesterday, um, or they got an email two weeks ago or whatever, you know, like they'd be able to view that, that message directly as long as it wasn't too old. Um, and that would be,
00:30:32
Speaker
You know, the only, the only situation where that wouldn't work is like for messages that only go out once every six months or something like that, things that are really rare, but those are kind of inherently going to have less of a need for this type of review because those are almost certainly going to be like internal messages that like,
00:30:59
Speaker
you know, maybe just have like an Excel spreadsheet attached to them or something. And it just doesn't matter what the contents is very much. Well, and you're, you know, your pruning could be, it could be like, keep the last 50 emails that each user receives or like keep the last 10 emails that each user receives, because then someone who got an email that goes out every six months, like it's going to still be in their email history.
00:31:29
Speaker
until they receive their 11th email or something like that, as opposed to just, just pruning based off of the create date of the, of the email. Right. Yeah. And you could even, you could even go so far as have like different pruning logic because though my only hesitation there is right. There's.
00:31:51
Speaker
there's like a certain class of message that just goes out to every user all the time, right? Like, and, you know, multiply that by a hundred thousand users. Like it just, yeah, I guess, you know, maybe it's just not that big a deal. I mean, Skylar's suggestion, we talked about this very briefly and you talked about maybe you just throw it on S3 so it's not in the database and that mitigates
00:32:19
Speaker
a lot of the concern, I think. So that's another interesting piece. Hey, just store the content on S3 and then link to it. And someone wants to know what it looks like. You just click the link and you're dropped onto an HTML page from S3. Let S3 handle the load of that. And I mean, these are small files.
00:32:44
Speaker
If I'm not mistaken by S3's pricing, like it's not going to cost anything to drop it on there because we're on S3, we're on EC2 instances when we'd be generating content. And then if it's never accessed, like you're paying basically nothing for storage of these files. Right.
00:33:03
Speaker
And the nice thing about that, it would solve this thing where, you know, uh, even if we decide to keep the files for, uh, rather than pruning them, but keep them for a few years or something, you know, and some member or user comes back and says like, Hey, I've never received this email. You know, we basically have like a permanent log and, um, you know, we could do that. I was also thinking the other approach that we could take is maybe drop some sort of like small config on the mailable that says like,
00:33:32
Speaker
prune this file in 30 days or something where, you know, if we want to, we say like, well, this email gets sent every day and like, we don't want a million copies of this. Um, you know, just this one needs to be cleaned up more often than others. So I think there's a lot of strategies, uh, I think that we could take. Yeah. You could just have a sane default and then if you needed to go into a specific mailable and say like, this one needs to be cleaned up more often. Mm-hmm.
Empowering Non-Technical Users in Email Customization
00:34:03
Speaker
And I think an interesting thing kind of switching topics a little bit is like customizing the actual content of the message, not the template of what the email looks like, but like the actual content.
00:34:19
Speaker
You know, you have non-staff or non-technical people that want to change what the email looks like, like the content within the email and making that easy, easier to handle. Yeah. I mean, this is definitely an issue for us because, you know, basically these messages never get changed because they, they like to change it.
00:34:49
Speaker
there's a sort of changing content goes through an editorial process usually, right? Where there's often sort of the stakeholder writes the content, but then it goes through an editor and then it comes to us and you know, it's, it's a pain to change it after the fact. And not everything goes through that process, but a lot of things do. Um,
00:35:16
Speaker
And so having an interface for managing that content and maybe even having some sort of system of flagging whether the latest edit has been reviewed. There's a bunch of interesting pieces there too where someone goes in and updates a piece of content and that could actually
00:35:43
Speaker
trigger a review from our editor to make sure that all the spelling and hyphenation and whatnot is right. I don't know if that would be v1, but it kind of opens up an interesting
00:36:04
Speaker
You know an interesting can of worms we get back into event sourcing all all the sudden Yeah, I mean at a previous job we would send transactional type emails to our customers customers It worked a company that made websites and these websites would have different contact related forms on them and at first like we would just send like we
00:36:32
Speaker
that my employer would send an email when someone filled out a form and we'd say like, Hey, thanks for filling out the form. And we'd email our customer saying like, Hey, someone filled out this form. Like, here are the results. But some of our customers like we want to change what the email body
00:36:51
Speaker
looks like that we're sending to our users, like our visitors. And so the approach that we took was basically like we would store markdown in the database and with like merge keys of like user.name and like
00:37:10
Speaker
user dot form field. Um, and then when the email was sent, we were like, does this, does this customer have a custom email body for this email? If they do, then like load up our like emails dot custom markdown file. Otherwise like use our default. Um, and it worked pretty well. Uh, you know,
00:37:38
Speaker
We got around customers having to learn Markdown by just using a tiny MCE WYSIWYG editor and then converting the HTML to Markdown to store in the database. And it worked pretty well because it also eliminated people from trying to put in video tags or a lot of things that aren't going to show up in an email provider's inbox.
00:38:06
Speaker
Yeah, it worked okay. It was just, we didn't have previews. It was just, here's to your form field and here's like your, I don't know, merge tags, but it worked pretty well, I would say. Yeah. I think that Markdown is definitely a good, uh,
00:38:26
Speaker
I don't know, in between or a place to settle on something like this because even if you don't use like a WYSIWYG, I think that for the type of content in email messages where it's like,
00:38:44
Speaker
You really aren't, you don't want to let them do very much formatting, right? It's a lot easier, except for links. So maybe having like a link helper. And then like I've looked at, there's a tip tap editor, which is just another WYSIWYG. And actually, I should look, maybe Frola does this, because we use Frola for a lot of WYSIWYG stuff, and I think it's a fantastic editor.
00:39:11
Speaker
But what's cool about Tiptap is you can implement placeholder type functionality directly inside of it so that
00:39:30
Speaker
You know, the example that they have is like at mentions, right? You type in at and it gives you a select, a dropdown of like usernames. And then that is like a token in the message like that you edit, like you can,
00:39:46
Speaker
move or remove entirely. But once it's in as a token, it's like your users aren't thinking about something like handlebars or some twig syntax where it's like, I have to. And even I'm kind of amazed that Mailchimp hasn't done this because Mailchimp still uses the asterisk pipe variable name format for their merge variables.
00:40:16
Speaker
But yeah, like if you basically know a given message has...
00:40:24
Speaker
potential, like all these are variables available to this message, then storing that content in the database somewhere with like, you know, some sort of placeholder format and giving some sort of WYSIWYG editor experience. I think that that's like the dream.
00:40:47
Speaker
Yeah. Well, and the great thing about storing it as markdown is like, at least in Laravel, like Laravel has first-class email markdown support. Like all we had to do was drop the markdown into the markdown method on the mail and then like we were done. And it was, it made it really easy. We didn't have to do a ton of other work to, to have that.
00:41:11
Speaker
Yeah, I mean, like we used in TinyMCE, like we built a custom plugin that like you could click the button that was like username and user dot form input. Like we were able to have these buttons and it like showed up in the text as like bracket, bracket user dot name. But at least they didn't have to know the exact formatting of what that looked like. Yeah. I mean, and you know, in the end, obviously,
00:41:41
Speaker
people can handle a little bit of that sort of technical stuff as long as you give them card rails and do a little bit of like validation and stuff like that.
00:41:51
Speaker
Yeah, I like the markdown approach because I feel like some of the things that I'm sure everybody has noticed, people tend to copy paste Word documents and put them into email templates. And then there's a bunch of garbage in there. So I think having a really clean, easy format that doesn't give you too much creative ability from the user end.
00:42:20
Speaker
is a really good placeholder. And the nice thing about Markdown is you could also use the notifications where you could store the content, like that Markdown itself.
00:42:44
Speaker
Correct me if I'm wrong, if that's not how it works, but I'm pretty sure that you're basically, you can preview a sent notification in a database, like database mailables or database notifications. That's how it works. Yeah, and we only really do two mail in our notifications right now, but I know if you use two database, I don't know what format that's stored in. I'm not sure if it's marked out or not.
00:43:11
Speaker
Um, it's sort of up to you. Oh, really? Okay. Well, I mean, because it's stored in the database is like text and then it's however you want to then pull those out and display them, um, in your system. Oh, I see. Interesting.
00:43:27
Speaker
Yeah. Yeah. I mean, that's another thing that I think about is, you know, right now we have we've implemented some things as notifications, I think. But I think that was partially just like whenever notifications came out in Laravel, it was looking like that was going to be the like official way to send stuff out. But in reality,
00:43:57
Speaker
It doesn't feel like mailables are ever going away. Like a notification is sort of an additional abstraction layer that either
00:44:07
Speaker
I think the way we're doing it where notifications are really only ever going to mail is just sort of a needless abstraction. Um, but I do, I do think a lot about, um, particularly when we have folks who, you know, Marked a message from us as spam and then, uh, call up yelling that they didn't get the message. Um, like,
00:44:36
Speaker
having another way for them to look up all the messages that they've received from us would be really nice. But on the flip side, I often, I don't know, I just, I know personally, it really irks me when like I log into an app that I haven't been in for a little while, and there's like 35 notifications, and all of them are things that I already looked at in my email, but because
00:45:03
Speaker
they're two separate things, it's like there's no way, there's no reliable way to know. Although I think, did you say that you guys in your previous place tried to sync those up, Skyler?
00:45:22
Speaker
Yeah, so we have this situation where you have a user account and you can belong to multiple teams.
Integrating Email and App Notifications
00:45:30
Speaker
And in situations where you get invited to a new team, we would send you an email, but we would also send you an app database notification. And if you clicked the Accept Invite link in your email,
00:45:48
Speaker
in that controller, we would then go in and delete the invite notification from the database because you had clearly already been sent. Interesting. You'd already like access to that. Um, that was kind of like the, um, the only place where that type of notification was being used, but we kind of built, built it so that, um,
00:46:12
Speaker
it was easy to, you know, I could foresee other, other emails. Like maybe you track when it was, when there's a click or if it was opened, those, those like opens are really finicky. Right. That makes me nervous. You know, so like you can't necessarily trust the open, but, um, the other thing that, you know, I could see you doing is like,
00:46:38
Speaker
maybe your database notification has an expiration date. And so if it's over, you just prune them, like prune notifications that probably don't matter. Or just mark them as red. Or mark them as red, yeah. But in this case, if you clicked the email, then we would delete or mark it as red. I think we marked it as red, that the notification was in there.
00:47:05
Speaker
But if you were in the app and you clicked it then it was marked as red and like you still got the email but You know that it didn't I don't know a way to unsend an email but at least at least in the app like we knew they clicked at the link because they landed on their like accepted page and
00:47:24
Speaker
Yeah. Yeah. Okay. I, I think I was, I thought that maybe you were trying to sync up with like, uh, you know, an open, um, webhook from centigrade or something. And that's just me. I don't, I feel like that's on too unreliable. It's too, it's too unreliable. Like I use hay for my personal email and they claim to block
00:47:46
Speaker
all of those open and click links. I have no idea if that's true. If it's true that they can fully block all of it, but I don't think those are reliable. I know Apple's privacy email settings make it much harder in the mail app to track opens and clicks.
00:48:07
Speaker
Yeah, I mean, even Gmail does that, I believe, where it's not like... It used to be that the message never even... The contents of the message wasn't parsed until you clicked on it in Thunderbird. Do either of you guys remember Thunderbird? Oh, yes. Yes. You click the message in Thunderbird and it would
00:48:36
Speaker
download the contents from the server at that moment and parse the HTML and render it, right? And that's like, then for sure, you know that that's the first time that that, like if it's fetching an image or whatever, that's the first time that that image was fetched. But nowadays, no email client works that way. So they're all loading the message
00:49:00
Speaker
usually on receive and, you know, parsing it for spam and, you know, potentially like proxying the images and all that stuff. Yeah. So like we don't use that. We were basically like managing the click. And if you clicked on it, you land on our, you eventually land on our controller and, and then we just had a like, uh, notification, like Mark is red method or,
00:49:26
Speaker
on the, I forget exactly what the method was, but it was like very easy to just link those together. Right. Um, shoot.
Handling Email Unsubscribes and Future Improvements
00:49:41
Speaker
I was thinking, what if we talk about email unsubscribes, right? Like you want to unsubscribe for an email. And I was thinking about this because, you know, theoretically what we could do is create like a dashboard that lists the emails that we kind of have set to go out, maybe like in some sort of list that we curate.
00:50:07
Speaker
And the only thing the user would have to do is just say, well, I don't want to receive past due reminders, right? From you guys ever. And, you know, at the time that that reminder is set, you know, we would then save that like fully qualified domain, uh, class name into a database.
00:50:25
Speaker
And at the time that it's supposed to be set, all we're going to say is like, hey, but make sure that this person is not unsubscribed from this fully qualified class name. And then that way we just skip sending an email to that person because they've just unsubscribed from that particular email. I think it's like a pretty quick solution to that because I know that that's also something that's fairly challenging.
00:50:54
Speaker
Yeah, that's a good, I like that idea. I know that a lot of the email service providers, I'm pretty sure that SendGrid has a way to
00:51:07
Speaker
basically inject an unsubscribe link into a message. And if you provide the correct metadata so that they know what the grouping or what the idea of that message type is, they can handle that for you. But I do, yeah, I like the idea of just sort of
00:51:32
Speaker
Again, it'd probably be something where you'd want it to be opt-in, right? Where any given mailable you could add like an interface to, to say like, this is unsubscribable or something like that. And then we just present that list to the user and they could say, oh yeah, I don't want to get these messages.
00:51:51
Speaker
Yeah, I think the other thing is we have to, I think, consider that not everybody uses SendGrid or some other male gun or something else. And if you look at SES, it's pretty like bare bones. And I feel like a lot of people use that. And I think having an app solution,
00:52:14
Speaker
is still worthwhile rather than potentially just having unsubscribes on the mail server and then your app is still dispatching these emails for everybody. I don't know. That was just my quick thinking as you were scratching your head there real quick thinking about what you were going to say. But I think overall, we talked about the configurable recipients feature.
00:52:42
Speaker
I really like that approach. I think we could probably improve on it a little bit with maybe some roles or groups. I think that's a really clever solution to manage which groups of people get these emails as well.
00:52:59
Speaker
And obviously configured emails like the content is obviously a huge thing. You know, I've looked at the furlough does offer a plugin for markdown. I think it's a good solution and using something like handlebars or, you know, even some bare bone, you know, parsing script also makes sense. So I like it.
00:53:21
Speaker
Yeah. And then you could do the same thing where it's, um, you know, it's a, it's, it might still need to be like a trait because you, you probably are always going to need to map.
00:53:36
Speaker
the properties on the mailable, right? If the mailable receives like two Booleans and a user object, right? Like, okay, we could just write a thing that maps the user object, or maybe even for all models, you just do two array and you just like present the array keys as the options.
00:54:04
Speaker
but you'd still probably need some intermediate thing that's like, uh, these are the variables that are available to this mailable. Um, and I, and honestly attributes, yeah, some PHP attributes maybe. Um, but even that, like,
00:54:24
Speaker
I think you'd wanna curate for any given message, even for the user, you probably don't need to expose all the different attributes of a user to the mailable. You'd wanna be like, okay, here's their display name, here's this city, state, country, different pieces of information that are gonna be relevant.
00:54:55
Speaker
So there probably need to be an intermediate step there too.
00:55:00
Speaker
Yeah, I agree. I feel like a lot of times what we do is we would do like a for each loop inside the template. You know, let's say we're listing a list of users and then we call like some sort of special function on a user like, Oh, give me their full name, which is just concatenating their first and last name. And we do that fairly regularly, but it seems to me like it has to happen beforehand inside that template and just passes an array, you know, like.
00:55:27
Speaker
Well, right. I mean, right there, that's a great example of like, if you have a loop inside of your message, like this solution does not, does not, unless your message, unless you want to let a, you know, include a full templating language that has things like loops and conditionals, like,
00:55:48
Speaker
Um, that's just not going to be possible either. Yeah. You have to do that loop. You would have to like map it or you create your mail. You create your mail merge tag that is like.
00:56:01
Speaker
Here's the list of exams you took over the last 18 weeks or like the last quarter. And it's like, well, here's your, you can choose where you want that list to go. You don't get to necessarily like change what the list says, but like, here's your, here's your mail merge for like courses taken last quarter. And, uh, you put that in somewhere.
00:56:29
Speaker
Right, and then you just have a separate view that you render and then pass that in as a string. Yeah. Yeah, that makes sense. That wouldn't be that bad. So I'm not 100% familiar with the mustache templates. I know that, Chris, you said you've had some experience. Would it be possible to have a more data-rich
00:56:53
Speaker
environment there or no? It would be, but then you're just like asking a lot of the end users. Like you said, you were basically like writing raw HTML and then you ended up having to do it all. It's kind of like if your end users like at most they customized their MySpace pages back in the day, like
00:57:16
Speaker
You just gotta make it easy or no one's gonna customize it or they're not gonna wanna touch it or they're gonna ask us to touch it. And then we're gonna have to leave our IDE and use a forum. I think there's probably, I don't know, maybe a bit of a pipe dream about just allowing an everyday person modifying mail, right? Maybe they'll modify a little bit of the content, but I feel like
00:57:42
Speaker
You know, just even us writing emails, you know, the writing the actual mailable class and the views and everything like, you know, it's fairly technical, like even this loop and, you know, some of, I don't know, some of the decisions, some of the variables that are displayed.
Developer Challenges in Email Template Management
00:57:58
Speaker
And I feel like, I don't know if it's really possible to give a lot of control to someone who is non-technical to update emails. I know that people do this and obviously Mailchimp and WordPress and stuff like that.
00:58:14
Speaker
I think once there's a little bit of complex logic, you almost have to like you as a developer. For example, let's just say you want to include some password reset link. Well, we obviously, let's say, create that password reset link inside the mail, but we pass it down as a variable that can be consumed. But it's almost like, well, we want to make sure that that link is displayed.
00:58:44
Speaker
You know, whereas like the end user could be like, well, I'm not going to display it. Um, so I feel like in those contexts though, like you could just make your, like you're providing a introduction to the, to the password reset.
00:58:59
Speaker
But the actual button that renders the reset link, that could just be hard coded in the template. But we're letting them customize everything else. I see. There's some options there. Sorry, Gracie, we're trying to say something.
00:59:15
Speaker
No, no, I mean, I think you were, you're getting at the same thing that I started thinking about, which is this brings me back to Medusa, like, yes, right? Internally, we have this sort of headless CMS concept where, you know, there are lots of pages on a website where
00:59:39
Speaker
You want certain parts of the page to be editable but a lot of the page is either dynamic and shouldn't be editable or like there's a lot of like very sophisticated markup and CSS to make like
00:59:55
Speaker
you know, some fancy, I don't know, UI component and like you don't want someone to be able to edit that. You just want them to be able to edit the like headline text that shows above that and maybe like the paragraph that shows below it and then like the ultra text at the bottom, right? And so our solution for that is we have this CMS where you basically wrap
01:00:22
Speaker
like editable portions of a page in these tags and then only those elements can be edited on the page, but the rest of it, like we have full design markup control of. And, you know, just like listening,
01:00:41
Speaker
listening to us talk about this, it's coming back to that almost here where it's like, actually, maybe the ideal is not letting people edit the messages, right? It's giving people a nice way to customize the parts of the message that they're actually
01:01:03
Speaker
going to change, right? And maybe you still need to do some like merge variable support there, but V1, you probably don't need to like for the first pass at this, the message could be like, hi, first name, comma, and then you have a paragraph that's editable.
01:01:24
Speaker
and then you have a table of the exam sessions, and then you have a salutation paragraph that's editable. Internally, we could even render this using Medusa right now, and you'd set the defaults, but if someone wants to go in and change that introductory paragraph, they could easily go in and do it.
01:01:54
Speaker
I mean, it has the trade-off of we're kind of going back to the beginning where now you do need to have like sort of sample data for any message because we need to be able to render it to give them a way to edit it. But given that trade-off, it comes with the benefit of being like, yeah, we don't, not only do we not have to, but we kind of don't want
01:02:24
Speaker
to have like non-technical users thinking about loops and tables and like, you know, especially with email content, like the, the just outlandish efforts you have to go to to get like markup to work for anything that's not really just like a paragraph, um, you know, like six nested tables with different like, uh, padding and, and via line settings and stuff. Right. Um, and that,
01:02:53
Speaker
That certainly is appealing. Yeah, I really like the approach of this. And I was going to ask earlier, is Medusa a public project, Chris, or is this something just in our world? It's not yet. OK, I hope to make it public someday, but it's not an estate that it can be.
01:03:11
Speaker
Yeah, I really like this kind of solution where we give enough to make some sort of change to the non-technical person. But overall, they cannot change the reset link, not being displayed or not properly put in as a markdown piece of content.
01:03:33
Speaker
really good solution to this kind of like customizing the email and I think even for developers I feel like one of the challenges that I have or that I kind of dislike about writing email in general is that you're kind of flying blind as you're writing the template and then you kind of like send yourself that message to see how it looks like and then you open up whatever flavor of local email parser tool you have and
01:04:01
Speaker
you see it and then you go back and you modify it and it's like, by the time you align everything correctly, you know, you switch the tab like 20 times. Whereas having some sort of like online, you know, in, in app preview is like a pretty good, um, you know, solution in my mind. And, and it's not like re realistically, it's not like every message needs to have this support, right? Like it's only,
01:04:29
Speaker
probably 10 emails that staff really are ever gonna wanna edit. And obviously that's gonna be different case by case for different organizations. But I think for us, that's true. Like most messages that we send out, there's just not a lot to it, right? And it's never gonna change. It's really things like welcome emails where maybe, like it would be great if we could
01:04:57
Speaker
have a way for staff to be able, like, you know, we're doing this convention in October, like, it would be awesome if someone could go into the welcome emails that are going out and add just like a little, Hey, and did you know that internet she is hosting this convention in October, right? And of course, then they have to remember to go back in and remove that, but
01:05:20
Speaker
I think there's a huge upside to letting folks have more control over some of those messages, and it wouldn't have to be a ton. I think Bogdan's idea about unsubscribes, we got off of it, but I'm going to bring it back because it was a nice segue into this last piece that
01:05:43
Speaker
I've been thinking about a little bit. We don't really have the use case for yet. This is more along the lines of what you were talking about, Skyler.
01:05:52
Speaker
when you're sending messages, not to your customers, but to the customers of your customers, right? Where your customer needs, you know, wants more ownership over that message. And the message contents is one piece, but also the logic is another piece, right?
Customer-Driven Email Logic and Scheduling
01:06:13
Speaker
So, you know, an example would be,
01:06:17
Speaker
There's a big tool in the home inspection world that lots of home inspectors use to manage their customers and manage sort of like marketing automation flows for their customers and all sorts of integrations. And I know a big component of that is sending out emails to their customers
01:06:47
Speaker
at different points, right? Like, you know, your inspection is scheduled or your inspection is coming up or thanks, you know, thank you for having us at your home. Like, here's some details about the inspection we just performed, like all these different steps. And I don't know, you know, this is just sort of an example that I can think of. I don't know how much customization they allow or how they handle it, but
01:07:14
Speaker
I'm sure that they get all sorts of feature requests for more ways to control, like, well, I don't want this message to go out five days before the inspection. I want it to go out seven days or three days, or I want one to go out seven days, three days, and one day. You know, like, I think there's an infinite number of possible scenarios like that.
01:07:40
Speaker
And so, you know, we have a use case that is sort of potentially gonna be similarly flexible, where I've just been thinking about, like eventually, if this feature that's mostly internal right now ever gets live for our members to use outside of like this one specific context, they're gonna start wanting those same things.
01:08:11
Speaker
maybe you're going to receive a report about some records in the database, and maybe they're going to want to say, I want that report every month. One person might say, I only want the report every month, and another person might say, I want the report every week, and another company might say, we want this report every day. That's obviously a whole, whole can of worms because I don't know if you can, we're basically describing
01:08:40
Speaker
a programming language. But I have just been thinking like, what approaches might you take to allow for that type of flexibility in not just like the message content, but actually like, you know, the logic around if and when certain messages are sent.
01:09:06
Speaker
So one of the ways I've managed to solve it in a multi-tenant context
01:09:13
Speaker
is there's one layer of a lab that is a multi-tenant app that I have. One of the features that I have is like, let's say you're scheduled, just for context, this is like a scheduling platform, like a work schedule management system, where you're scheduled to go on a shift that starts, let's say, tomorrow at 8 PM. One of the features that it offers is,
01:09:44
Speaker
there's a way to send a upcoming shift notification. For example, like 24 hours before your next upcoming shift, it would send an email saying, hey, don't forget that you're going to work tomorrow at 8 PM. This is just a reminder. But a different tenant may choose a different time. One of the ways that I was able to solve it is I have a setting table and it would just say,
01:10:13
Speaker
this type of notification is sent, let's say, 12 hours before or six hours before. The way that would work is there would be a scheduled job in a kernel that runs every minute or every hour you can do, probably every hour is fine. Once that job is ran inside the command, you would just loop through all of the tenants and say, okay, well, give me the tenant and give me the setting.
01:10:43
Speaker
and then find me all of the shifts within this time frame, and then dispatch the emails. So that is one way that you could potentially do. And I can imagine this is something that's similarly happening to this system that you're describing, Chris. Yeah, I think that makes sense. And I imagine that something like this is just always going to have
01:11:09
Speaker
you know, they're always just going to be boundaries of what, what's going to be allowable. Um, cause I could even see in that scenario, if you have another tenant who, um, wants to send out a reminder 24 hours before and two hours before.
01:11:25
Speaker
you could always just have like two emails. One is like, you know, shift first reminder and shift second reminder, you know? And then like, if you have a tenant who wants three, you could just add shift third reminder, right? And just by default, the new ones are just set to be not enabled for anyone. But you know, I think that that,
01:11:51
Speaker
And maybe that's the best solution. I've been thinking a little bit about like, what if instead of having like a sort of like shift first reminder message template, instead you basically think about, and I do not,
01:12:20
Speaker
I'm not bringing up event sourcing again. I'm just going to pre preface this with, but you basically think about these as events, right? Where, um, what if instead you're just saying, okay, there's a, um,
01:12:37
Speaker
There's like an hours before shift event that fires every hour for 48 hours. That includes one argument, which is like number of hours until shift. Right. And then you give your clients basically a way to say, you know, when.
01:12:58
Speaker
this happens with like this number of hours remaining, send this email, right? And that way, if I want to send out an email every hour for 48 hours leading up to a shift, I could create 48 custom messages. And all of those are just basically saying, when this event happens with these arguments, send this message.
01:13:20
Speaker
And like, I imagine that there's a way to kind of, you know, these are events, I would think of them as purely events that are for customer consumption, like you would keep them totally separate from the rest of your applications events. And you'd like only trigger them from like a scheduled job or something like that.
01:13:43
Speaker
But then if a customer comes to you and says, you know, I want to be able to like reach out to people who are still on staff, but haven't like picked up a shift in six months, you know, like, um,
01:14:03
Speaker
it wouldn't cost you that much to basically just like add a new scheduled job, right? That once a day performs that query and triggers that event. And now like that use case is supported. And I feel like that may be a really flexible way to approach this problem.
01:14:25
Speaker
But the downside is it may be a little more technically difficult for customers to understand because now they're not thinking like, this is what the customer reminder email looks like. They're having to think like,
01:14:42
Speaker
I want to send this email when like 24 hours after like on the like job happened in past event when ours is 24 or whatever. Like you'd have to do a lot of work to make the UI nice. Yeah. I mean, it's, it's almost a little bit like, uh, like drip campaigns, I think, um,
01:15:09
Speaker
you know, like male male coach, like spotty's newsletter thing. Like their latest version has this drip builder where you can like send automated emails on a schedule and there's like ways to like opt out of those. And the founders of honey badger built a tool called Hey, Hey, yeah. Hey, yeah.dot email. H E Y a.dot email. And it's similar in that you can like create these campaigns. Theirs is all code generated.
01:15:40
Speaker
Um, but it's almost like we, we could have these campaigns that that can be built where they're like, all right, well, your campaign starts when the job was scheduled or the campaign starts when the user fills out a like request for something, a request for an inspection. And then five days after, or four days before the scheduled inspection,
01:16:10
Speaker
It's a little less flexible than what you were saying because we're kind of providing them what those campaigns are, specific, but it may be a little bit easier to build a UI that lets people design these. They could add eight emails to their campaign. I mean, honestly, as I think about it,
01:16:37
Speaker
I feel like a rule builder UI, I think the trick is you'd need to, you'd basically need to map an event to a label that makes sense in a rule builder context.
01:16:59
Speaker
But then it'd be pretty easy to just say, OK, I want to send an email. When do I want to send the email? And the options are after a inspection is completed, or before an inspection is scheduled, or before an inspection is performed, or when an inspection is scheduled.
01:17:23
Speaker
essentially have to think about these events as like strings that make sense in that context. And then you would just have dropdowns for any of the parameters, right? So like, I want to send this after an inspection is performed. And when you choose that from like the rule builder, then you have the option to say, like, after x number of hours, right? And like, you could set it to zero to have it happen immediately. Or you could set it to 10.
01:17:52
Speaker
or 400 or whatever you want. And that would be pretty easy for people to use, I think. Yeah, I've certainly ran into one of these workflow automation tools before. And it was a very user-friendly thing where it was kind of like a little configuration or WYSIWYG builder type of thing, where it would say,
01:18:21
Speaker
with an invoice sent to a client, also send a text message later or something like that. It seemed pretty easy in the UI portion. I don't know how complex it sounds, a bit complex, but it's certainly one of those things where it would give a lot of flexibility where you could have just various events, like you said, that are able to happen and then
01:18:49
Speaker
You would just, I suppose, store them in a database and add some sort of timeframe that says like, well, when an invoice is generated, then 24 hours later, send a text message as well to remind them to pay that invoice.
01:19:11
Speaker
Right. So I think, you know, it's pretty plausible to do something like that. Um, it's just, I think one of the challenges is the UI component as well. Yeah. Let's just build Zapier real quick. Oh, Zapier. That's right. That's what that is. Um, no, it's, it's an interesting concept. Yeah. I mean, and this is one of those things where we don't have, we, we at internet, you don't have to figure it out quite yet, but I think it's, um,
01:19:40
Speaker
It's definitely part of this conversation. It's been on the edge of discussions from time to time. Not only do we want to be able to customize other parts of the message, but
01:19:54
Speaker
I mean, even, even going back to Skylar's first, um, first example, like maybe, maybe it's just like, instead of having vacation mode, you just, the, the solution, obviously having vacation mode would be great, but if there was more, um, user level control of these messages, like just having a way for them to go in and say, uh, you know,
01:20:18
Speaker
update the logic to be like, and the dates are not between these two dates, you know, like, and it just don't send anything on New Year's Eve or whatever. Yeah. Like you could, if you had sort of just like a generic rule builder, um, yeah, it could be, um, it could be another way to solve that problem. You know, obviously it introduces a lot of complexity though.
01:20:46
Speaker
Or you could just use Zapier and MailChimp and, uh, then it wouldn't be over-engineered though. Well, right. I mean, what's the point of that? I did think like that, that may honestly be the best solution is just like, uh, build a bunch of Zapier triggers and be like, Hey, if you want to like,
01:21:09
Speaker
If you want to send out email messages based on things that happen inside the app, you just connect whatever email provider you want with our Zapier integration and you're on your own.
01:21:23
Speaker
Yeah, I don't know. Yeah, I don't know. I feel like that's talk first for not this podcast. This is about over-engineering. Yes. But yeah, I mean, I like I like that approach. I think it's very over-engineered.
01:21:41
Speaker
Well, this feels like a pretty good place to stop. Um, I, I feel like I want to mull over a couple of these pieces. Um, but I do really like the idea of using, I like the idea of using Medusa edit, um, email contents so that you can just like, um, zero in on the few pieces of those messages there that ought to be edited and you don't have to deal with any of the,
01:22:11
Speaker
nonsense of like, oh, yeah, are they going to accidentally like remove the button styling from the link or whatever, you know. And that feels like a good a good solution there, even if it does mean that we have to come up with some sort of like way to pull in defaults for preview or whatever. But yeah, all in all, I'm pretty I'm I'm pretty satisfied with where we got to.
01:22:40
Speaker
Same, same. I feel like if, uh, if people have opinions, be sure to, to share them on like Twitter and Macedon and threads and a million other apps on social blue skies, or if you're coming to layer con in like a week, uh, come find us, we'll be there. Yeah. And, uh, I'm bringing some over-engineered stickers. So come and grab one. Nice. All right. Let's call it. See ya.