If you do
strace mail <dest> < .
you can see what happened (although you have to look closely). On a Linux system (as a comment notes, other Unix systems may behave differently if a read of a directory succeeds), there are about 200 lines of output, much of it initialization, but there are three very significant lines, in my case lines 153, 165 and 191:
...
read(0, 0x556829edb730, 8192) = -1 EISDIR (Is a directory)
...
write(1, "No message, no subject; hope tha"..., 39No message, no subject; hope that's ok) = 39
...
write(4, "Date: Sat, 10 Oct 2020 23:19:22 "..., 212) = 212
...
exit_group(0) = ?
+++ exited with 0 +++
IOW, it tried to read file descriptor 0 (its standard input) and got an error EISDIR: that's because the shell redirected . i.e. the current directory as its standard input and read is not allowed to read a directory. But the mail program ignored that error, wrote a message on its stdout (file descriptor 1) that there was no message and no subject submitted to it and that it hoped that that was OK, then proceeded to compose a mail message and write it to file descriptor 4, which presumably is plumbed up somehow to send the message (the message consists of 212 characters). Note also that the program exits with 0 status (normal exit).
If you try the same thing with cat or tr as @thanasisp suggests in his answer, you will see a slightly different result. Those programs still try to read from file descriptor 0 and get the EISDIR error - but they do NOT ignore the error; instead, they exit with an error message and non-zero status:
$ strace cat < .
...
read(0, 0x7fc27daec000, 131072) = -1 EISDIR (Is a directory)
write(2, "cat: ", 5cat: ) = 5
write(2, "-", 1-) = 1
openat(AT_FDCWD, "/usr/share/locale/en_US.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en_US.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en_US/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
write(2, ": Is a directory", 16: Is a directory) = 16
write(2, "\n", 1
) = 1
munmap(0x7fc27daeb000, 139264) = 0
close(0) = 0
close(1) = 0
close(2) = 0
exit_group(1) = ?
+++ exited with 1 +++
But there is no difference in how < . is treated: in both cases, the shell associates a file (the current directory) with file descriptor 0 (the standard input) of the executed program. But the programs choose to respond to the error differently. That's all.
And BTW, the answer by @thanasisp is spot-on and answers most of your questions (even if it elides a bit the subtle difference between the mail command and e.g. tr or cat, which is what I concentrate on in this answer).