-
-
Notifications
You must be signed in to change notification settings - Fork 128
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support mocking SMTP #374
Comments
Hey, @kentcdodds. I took a look at how Nodemailer works, and as I suspected, they tap into a raw socket connection via the Here's a rough representation of those network layers:
The Socket layer seems to be the highest layer we can capture requests over SMTP and other non-HTTP protocols in Node.js. That's also how Nodemailer and other implementations do that since Node doesn't ship with a standard API to make SMTP requests easier as it does for HTTP requests. My approach to interception is that it should be unified, as in I'm not eager to ship logic that's specific to certain libraries or even protocols. A good solution here would be to lower all the interception logic to the Socket layer, including the interception of HTTP requests. But, as I've mentioned, that can prove problematic in some use cases. An incremental solution would be to try implementing something like a I'm currently busy with the Fetch API primitives adoption in MSW and I'm excited it's reaching the finish line. I won't have any time to look into this feature in the nearest future, I'm afraid. This can be a great improvement for the upcoming releases though! |
Thanks for explaining all of that! If this becomes a high enough priority for me then I'll signal in here that I've started looking into it myself. Cheers! |
I also recall that one technical challenge was to parse socket messages. At the Socket level, you are operating with plain text sent over the network so you receive chunks like
These strings have to be parsed to do request matching and turn the finished request message into a Fetch Request instance. Sadly, Node doesn't expose their parser publicly (it's written in C). |
@kentcdodds, I've given the Socket-based interceptor a try in #375 and it mostly works. I've managed to work around the actual socket connection and let the socket think it's always connected, even if to a non-existing host. Responding with a mock message also works based on the test I wrote. If you ever get to play around with this, take a look at that pull request, it's a good starting point. |
Wow! Very cool! |
The main challenge at the moment is the import order. Since you're often using a dependency that imports // OK!
import './interceptor'
import { sendMail } from 'third-party' // imports already patched "net"
// Nope :(
import { sendMail } from 'third-party' // imports and "remembers" unpatched "net"
import './interceptor' Because of this, it cannot be applied lazily (i.e. in your This must have a solution since it's not a problem for the
|
When talking about consumable third-party packages like Nodemailer, the interception becomes more complex as a result of the implementation details of those packages. For example, Nodemailer can utilize three different protocols to implement email transfer and switch between them as it sees fit. A single interceptor cannot guarantee it will intercept an email sent with Nodemailer simply because of that. This opens up a more interesting discussion about low-level interception and high-level usage needs. When you're using tools like Nodemailer, all you want to do is intercept that sent email and maybe mock the server's response. You don't want to think (or even know) how exactly that email transfer is being implemented under the hood—that's too low-level for you. But from the Interceptor's standpoint, it doesn't tackle specific tools but instead tries to provide an interception on the basis of common ground (e.g. let's patch This reminds me a lot about WebSockets and what makes their support challenging. No libraries are using the
Which already gives us 2 different areas to work with. I think SMTP is very similar in this regard. I suppose we can implement something like a |
That makes sense. Might be more work than it's worth 😬 |
With #515, mocking SMTP and other protocols in Node.js becomes a matter of introducing a respective parser. So, it's possible! |
I'm circling back on mswjs/msw#751
I would like to make my
sendEmail
function easier to migrate between different email providers and using the SMTP standard is the easiest way to do this. But then I have to resort to doing weird things to mock it (nodemailer specifically) out during development and testing.Any chance MSW could support mocking these kinds of requests?
The text was updated successfully, but these errors were encountered: