Compare commits

...

29 Commits
v1.2 ... master

Author SHA1 Message Date
Silvan Jegen d5e202b30f fix calloc argument order
These were found through gcc warnings.

Message-ID: <20240518093029.4799-1-s.jegen@gmail.com>
2 weeks ago
Leah Neukirchen a4502e83c4 mseq: delay loading of the sequence until we need it
This fixes many cases where mseq is called from a wrapper
but only file names are passed.

Reported by ccx.
3 weeks ago
Leah Neukirchen cf5493bb19 mmime: don't create empty lines when wrapping long words in headers.
Reported by Solène Rapenne.
3 months ago
Leah Neukirchen 76f5656401 mblaze-profile: mention Delivered-To
This was forgotten as part of e1e5bfe5f.
4 months ago
Johannes Thyssen Tishman 5310c4ea38 mcolor: Add coloring support for diffs
Closes: #249 [via git-merge-pr]
8 months ago
Leah Neukirchen 59ee2e0ab9 mgpg: use quiet to only print errors
Else it can happen that gpg output is prepended to the message we
want to decode, and recursive decoding fails.
10 months ago
Meudwy 07d064fc11 mdirs: add Maildir profile key
When `mdirs` is executed without any arguments, look for the `Maildir`
key in the profile and use that instead (if set).

Closes: #245 [via git-merge-pr]
10 months ago
Meudwy 75de7d47da minc: read directory names from stdin
This matches `mlist` where it can take directories as arguments or via
stdin.

Closes: #244 [via git-merge-pr]
10 months ago
Leah Neukirchen 43f2cb8b49 mscan: only spawn pager when stdout is a tty
We still get the terminal size for when users manually page, e.g.
mscan | less

This is consistent with how mshow already works.

Fixes #243.
11 months ago
Johannes Thyssen Tishman 23a9e7022e Quote command expansion to prevent word splitting
This is necessary to support maildir paths that contain spaces.

Closes: #242 [via git-merge-pr]
11 months ago
Johannes Thyssen Tishman ce435c8f6f Add Drafts profile key
Allow the user to set a Drafts key in profile to store draft messages
and sent messages separately if Outbox is set.
12 months ago
Mark Hills 786238551a Document a reasonable practice for deleting mails
Discussed in #236.
1 year ago
Leah Neukirchen 1838158ef1 blaze822_priv.h: use proper lc/uc
Mail headers may contain characters where the simple definition breaks,
which results in wrong formatting on output.

Fixes #235.
1 year ago
Leah Neukirchen cccf01cb9a mrep/mbnc: use mseq -r as leading whitespace is now significant.
Reported by lhynes.
1 year ago
Leah Neukirchen 2365f48f06 mcolor: print out form-feed 2 years ago
Michael Forney 74e77845c3 mmime: include strings.h for strncasecmp 2 years ago
Michael Forney 1babebc12c mlist: use fixed-width integer types for struct linux_dirent64 d_ino and d_off 2 years ago
codesoap 8d543fdb21 mcom: allow spaces in sequence for mbnc and mrep
Closes: #231 [via git-merge-pr]
2 years ago
Omar Polo 9d66764434 mrefile/mdeliver: -M needs the `fattr' pledge promise for utimes(2)
Message-Id: <2Z5ISO2SNIGZU.2E8B1F41F84RV@venera>
2 years ago
gco e6813fd07c solaris needs termios.h and __EXTENSIONS__ for TIOCGWINSZ and winsize 2 years ago
gco 877569a6f3 if -fstack-protector-strong is used, it needs to be specified for both compiling and linking
Closes: #229 [via git-merge-pr]
2 years ago
jgart bbc754e2a1 List commands ~respectively
Closes: #228 [via git-merge-pr]
2 years ago
Alyssa Ross bb3dacc604 blaze822: don't try to open /dev/stdin
Use the same check is blaze822() as in blaze822_file() to ensure that
we don't try to open /dev/stdin, which is non-POSIX.
Message-Id: <20220523170921.2623516-1-hi@alyssa.is>
2 years ago
Julian Rother 793e22ecb7 mthread: reduce memory usage
mthread keeps header data of all messages in memory until it exits without
ever using it. With this change it frees the header data of each message
right after processing it.

Closes: #222 [via git-merge-pr]
2 years ago
Leah Neukirchen 47c5707d50 add contrib/mopenall 2 years ago
Leah Neukirchen cd5bc471f3 man: misc manpages nits
Found by Omar Polo.
2 years ago
Lucas e951b0ba27 mmime: allow to relax body line length limit
Message-Id: <10e22a318b5c70d89432d85ecd8cb8ce1796a51d.1643116719.git.lucas@sexy.is>
2 years ago
Leah Neukirchen fa27d73ddd mshow: don't spawn pager with -t 2 years ago
Leah Neukirchen 3496545358 mflow: fixed lines were not wrapped, add test suite
Reported by ninewise.
2 years ago

@ -1,5 +1,6 @@
CFLAGS?=-g -O2 -fstack-protector-strong -D_FORTIFY_SOURCE=2
override CFLAGS:=-Wall -Wno-switch -Wextra $(CFLAGS)
LDFLAGS?=-fstack-protector-strong
LDLIBS=-lrt
OS := $(shell uname)
@ -25,10 +26,10 @@ SCRIPT = mcolor mcom mless mmkdir mquote museragent
all: $(ALL) museragent
$(ALL) : % : %.o
maddr magrep mdeliver mexport mflag mflow mgenmid mhdr mpick mscan msed mshow \
msort mthread : blaze822.o mymemmem.o mytimegm.o
maddr magrep mdeliver mexport mflag mgenmid mhdr mlist mpick mscan msed mseq \
mshow msort mthread : seq.o slurp.o mystrverscmp.o
maddr magrep mdeliver mdirs mexport mflag mflow mgenmid mhdr mpick mscan msed \
mshow msort mthread : blaze822.o mymemmem.o mytimegm.o
maddr magrep mdeliver mdirs mexport mflag mgenmid mhdr minc mlist mpick mscan \
msed mseq mshow msort mthread : seq.o slurp.o mystrverscmp.o
maddr magrep mflow mhdr mpick mscan mshow : rfc2047.o
magrep mflow mhdr mshow : rfc2045.o
mshow : filter.o safe_u8putstr.o rfc2231.o pipeto.o

@ -443,7 +443,10 @@ blaze822(char *file)
if (!mesg)
return 0;
fd = open(file, O_RDONLY);
if (strcmp(file, "/dev/stdin") == 0)
fd = dup(0);
else
fd = open(file, O_RDONLY);
if (fd < 0) {
free(mesg);
return 0;

@ -12,9 +12,9 @@ struct message {
#define isfws(c) (((unsigned char)(c) == ' ' || (unsigned char)(c) == '\t' || (unsigned char)(c) == '\n' || (unsigned char)(c) == '\r'))
// ASCII lowercase/uppercase without alpha check (wrong for "@[\]^_")
#define lc(c) ((c) | 0x20)
#define uc(c) ((c) & 0xdf)
// 7bit-ASCII only lowercase/uppercase
#define lc(c) (((unsigned)(c)-'A') < 26 ? ((c) | 0x20) : (c))
#define uc(c) (((unsigned)(c)-'a') < 26 ? ((c) & 0xdf) : (c))
// dirent type that can be a mail/dir (following symlinks)
#if defined(DT_REG) && defined(DT_LNK) && defined(DT_UNKNOWN)

@ -20,7 +20,7 @@ n=$(mshow -t "$tmp" | awk -F: '
/: application\/octet-stream/ {if (supported) print $1}')
if [ "$n" ]; then
mshow -O "$tmp" "$n" | $GPG -d 2>&1 || exit 0
mshow -O "$tmp" "$n" | $GPG --quiet -d 2>&1 || exit 0
exit 64
fi
exit 63

@ -0,0 +1,18 @@
#!/bin/sh -e
# mopenall [MSG] - open every attachements in xdg-open
[ "$#" -eq 0 ] && set -- .
f="$(mseq "$1" | sed 1q)"
[ -z "$f" ] && printf 'No message %s.\n' "$1" 1>&2 && exit 1
dir=$(mktemp -d -t menter.XXXXXX)
cd "$dir"
mshow -t "$1"
mshow -B -x "$1" 2>/dev/null
for f in * ; do
xdg-open "$f" &
done
wait
echo rm -r "$dir"
rm -r "$dir"

@ -1,4 +1,4 @@
.Dd June 18, 2021
.Dd January 27, 2024
.Dt MBLAZE-PROFILE 5
.Os
.Sh NAME
@ -49,15 +49,24 @@ The fully qualified domain name used for
.Li Message\&-Id\&:
generation in
.Xr mgenmid 1 .
.It Li Maildir\&:
If set,
.Xr mdirs 1
will use this maildir when no directories are supplied.
.It Li Outbox\&:
If set,
.Xr mcom 1
will create draft messages in this maildir,
and save messages there after sending.
will save messages in this maildir after sending.
.It Li Drafts\&:
If set,
.Xr mcom 1
will create draft messages in this maildir (defaults to Outbox).
.It Li Reply-From\&:
A comma-separated list of display name and mail address pairs, formatted like this:
A comma-separated list of display name and mail address pairs,
formatted like this:
.Dl Li Primary Name <myname1@domain1>, Name v.2 <myname2@domain2>, \[dq]Name, My Third\[dq] <myname3@domain3>, ...
The first of these that appears in the
.Li Delivered-To\&: ,
.Li To\&: ,
.Li Cc\&: ,
or

@ -163,6 +163,9 @@ thread it and look at it interactively:
Or you could list the attachments of the 20 largest messages in your INBOX:
.Dl mlist ~/Maildir/INBOX | msort -S | tail -20 | mshow -t
.Pp
Or delete messages beyond a certain age:
.Dl mlist ~/Maildir/INBOX | mpick -t 'mtime < \&"-365d\&"' | xargs rm
.Pp
Or apply the patches from the current message:
.Dl mshow -O . '*.diff' | patch
.Pp

@ -6,7 +6,7 @@
.Nm mfwd ,
.Nm mbnc ,
.Nm mrep
.Nd compose, reply, forward, bounce, send messages
.Nd compose, forward, bounce, reply, send messages
.Sh SYNOPSIS
.Nm mcom
.Op Fl Ar header Ar values\ ...

@ -1,4 +1,4 @@
.Dd Feburary 4, 2021
.Dd February 4, 2021
.Dt MDELIVER 1
.Os
.Sh NAME

@ -1,4 +1,4 @@
.Dd January 22, 2020
.Dd July 25, 2023
.Dt MDIRS 1
.Os
.Sh NAME
@ -17,6 +17,14 @@ for maildir
folders and prints them,
separated by newlines.
.Pp
If
.Ar dirs
is not present then use
.Sq Li Maildir\&:
from
.Pa "${MBLAZE:-$HOME/.mblaze}/profile"
.Pq if set .
.Pp
To
.Nm ,
a maildir folder is a directory containing
@ -36,10 +44,20 @@ Print folders separated by a NUL character.
.It Fl a
Traverse into all subfolders, without considering the maildir++ name conventions.
.El
.Sh ENVIRONMENT
.Bl -tag -width Ds
.It Ev MBLAZE
Directory containing mblaze configuration.
.Po
Default:
.Pa $HOME/.mblaze
.Pc
.El
.Sh EXIT STATUS
.Ex -std
.Sh SEE ALSO
.Xr find 1
.Xr find 1 ,
.Xr mblaze-profile 5
.Sh AUTHORS
.An Leah Neukirchen Aq Mt leah@vuxu.org
.Sh LICENSE

@ -17,6 +17,9 @@ by moving them from
to
.Pa cur ,
and adjusting the filenames.
If used non-interactively with no specified folders,
.Nm
reads directory names from the standard input.
.Pp
By default, the new filenames are printed,
separated by newlines.

@ -46,6 +46,14 @@ Override Content-Type for the toplevel part.
Defaults to
.Sq Li multipart/mixed .
.El
.Sh ENVIRONMENT
.Bl -tag -width Ds
.It Ev MBLAZE_RELAXED_MIME
If set,
.Nm Fl c
will relax the body line length check and only consider bodies with lines
longer than 998 characters need to be MIME formatted.
.El
.Sh EXIT STATUS
.Ex -std
.Sh SEE ALSO

@ -29,7 +29,6 @@ Read expression from
.Ar file
and only show matching messages, see
.Sx TESTS .
.Ar file ,
.It Fl T
Include whole thread.
.It Fl t Ar test

@ -7,15 +7,19 @@ function so(s) { return sprintf("\033[1m%s\033[0m", s) }
BEGIN { hdr = 1; if ("NO_COLOR" in ENVIRON || match(ENVIRON["TERM"], "^(dumb|network|9term)")) no_color = 1 }
no_color { print; next }
/\r$/ { sub(/\r$/, "") }
/^\014$/ { nextmail = 1; next }
/^$/ { hdr = 0 }
/^\014$/ { nextmail = 1; print(fg(co("FF",232), $0)); next }
/^$/ { hdr = 0; diff = 0 }
/^-- $/ { ftr = 1 }
/^diff -/ { diff = 1 }
/^--- .* ---/ { print fg(co("SEP",242), $0); ftr = 0; sig = 0; next }
/^-----BEGIN .* SIGNATURE-----/ { sig = 1 }
nextmail && /^From:/ { hdr = 1 }
hdr && /^From:/ { print so(fg(co("FROM",119), $0)); next }
hdr { print fg(co("HEADER",120), $0); next }
ftr { print fg(co("FOOTER",244), $0); next }
diff && /^-/ { print fg(co("DIFF_D",160), $0); next }
diff && /^\+/ { print fg(co("DIFF_I",40), $0); next }
diff && /^@/ { print fg(co("DIFF_R",226), $0); next }
/^-----BEGIN .* MESSAGE-----/ ||
/^-----END .* SIGNATURE-----/ { print fg(co("SIG",244), $0); sig = 0; next }
sig { print fg(co("SIG",244), $0); next }

26
mcom

@ -236,7 +236,9 @@ esac
hdrs="$(printf '%s\n' "${hdrs#$NL}" | mhdr -)"
outbox=$(mhdr -h outbox "$MBLAZE/profile" | sed "s:^~/:$HOME/:")
if [ -z "$outbox" ]; then
draftbox=$(mhdr -h drafts "$MBLAZE/profile" | sed "s:^~/:$HOME/:")
draftbox="${draftbox:-$outbox}"
if [ -z "$draftbox" ]; then
if [ -z "$resume" ]; then
i=0
while [ -f "snd.$i" ]; do
@ -249,13 +251,13 @@ if [ -z "$outbox" ]; then
draftmime="$draft.mime"
else
if [ -z "$resume" ]; then
draft="$(true | mdeliver -v -c -XD "$outbox")"
draft="$(true | mdeliver -v -c -XD "$draftbox")"
if [ -z "$draft" ]; then
printf '%s\n' "$0: failed to create draft in outbox $outbox." 1>&2
printf '%s\n' "$0: failed to create draft in outbox $draftbox." 1>&2
exit 1
fi
elif [ -z "$draft" ]; then
draft=$(mlist -D "$outbox" | msort -r -M | sed 1q)
draft=$(mlist -D "$draftbox" | msort -r -M | sed 1q)
fi
draftmime="$(printf '%s\n' "$draft" | sed 's,\(.*\)/cur/,\1/tmp/mime-,')"
fi
@ -321,7 +323,10 @@ fi
) fi
;;
*mbnc*)
set -- $(mseq -- "$@")
old_ifs="$IFS"
IFS=$NL
set -- $(mseq -r -- "$@")
IFS="$old_ifs"
if [ "$#" -ne 1 ]; then
printf 'mbnc: needs exactly one mail to bounce\n' 1>&2
exit 1
@ -340,11 +345,14 @@ fi
printf 'Resent-Date: %s\n' "$(mdate)"
(
IFS=$NL
cat $(mseq -- "$@")
cat $(mseq -r -- "$@")
)
;;
*mrep*)
set -- $(mseq -- "$@")
old_ifs="$IFS"
IFS=$NL
set -- $(mseq -r -- "$@")
IFS="$old_ifs"
if [ "$#" -ne 1 ]; then
printf 'mrep: needs exactly one mail to reply to\n' 1>&2
exit 1
@ -440,7 +448,7 @@ while :; do
if $sendmail <"$draftmime"; then
if [ "$outbox" ]; then
mv "$draftmime" "$draft"
mflag -d -S "$draft"
mrefile "$(mflag -d -S "$draft")" "$outbox"
else
rm "$draft" "$draftmime"
fi
@ -458,7 +466,7 @@ while :; do
stampdate "$draft"
if $sendmail <"$draft"; then
if [ "$outbox" ]; then
mflag -d -S "$draft"
mrefile "$(mflag -d -S "$draft")" "$outbox"
else
rm "$draft"
fi

@ -355,7 +355,11 @@ usage2:
if (argc != optind+1)
goto usage2;
xpledge("stdio rpath wpath cpath", "");
xpledge("stdio rpath wpath cpath fattr", "");
if (!preserve_mtime && !Mflag) {
/* drop fattr */
xpledge("stdio rpath wpath cpath", "");
}
targetdir = argv[optind];

@ -3,8 +3,10 @@
#include <dirent.h>
#include <limits.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "blaze822.h"
@ -72,6 +74,33 @@ mdirs(char *fpath)
closedir(dir);
}
char *
profile_maildir()
{
char *f = blaze822_home_file("profile");
struct message *config = blaze822(f);
char *maildir;
static char path[PATH_MAX];
if (!config)
return 0;
if (!(maildir = blaze822_hdr(config, "maildir")))
return 0;
if (strncmp(maildir, "~/", 2) == 0) {
const char *home = getenv("HOME");
if (!home) {
struct passwd *pw = getpwuid(getuid());
home = pw ? pw->pw_dir : "/dev/null/homeless";
}
snprintf(path, sizeof path, "%s/%s", home, maildir+2);
maildir = path;
}
return maildir;
}
int
main(int argc, char *argv[])
{
@ -86,11 +115,17 @@ usage:
exit(1);
}
if (argc == optind)
goto usage;
xpledge("stdio rpath", "");
if (argc == optind) {
char *maildir = profile_maildir();
if (maildir) {
mdirs(maildir);
return 0;
}
goto usage;
}
char toplevel[PATH_MAX];
if (!getcwd(toplevel, sizeof toplevel)) {
perror("mdirs: getcwd");

@ -145,7 +145,7 @@ main(int argc, char *argv[])
return 0;
}
args = calloc(sizeof (char *), argsalloc);
args = calloc(argsalloc, sizeof (char *));
if (!args)
exit(-1);

@ -1,3 +1,7 @@
#ifdef __sun
#define __EXTENSIONS__ /* to get TIOCGWINSZ */
#endif
#include <sys/ioctl.h>
#include <sys/stat.h>
@ -9,6 +13,7 @@
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <termios.h>
#include "blaze822.h"
#include "xpledge.h"
@ -29,28 +34,6 @@ chgquote(int quotes)
}
}
void
fixed(int quotes, char *line, size_t linelen)
{
chgquote(quotes);
if (column && linelen > (size_t)(maxcolumn - column)) {
putchar('\n');
column = 0;
}
if (column == 0) {
for (; column < quotes; column++)
putchar('>');
if (quotes && *line != ' ')
putchar(' ');
}
fwrite(line, 1, linelen, stdout);
putchar('\n');
column = 0;
}
void
flowed(int quotes, char *line, ssize_t linelen)
{
@ -96,6 +79,15 @@ flowed(int quotes, char *line, ssize_t linelen)
}
}
void
fixed(int quotes, char *line, size_t linelen)
{
flowed(quotes, line, linelen);
putchar('\n');
column = 0;
}
int
main(int argc, char *argv[])
{
@ -200,6 +192,11 @@ main(int argc, char *argv[])
if (delsp)
line[--rd] = 0;
flowed(quotes, line, rd);
} else if (rd == 0) { // empty line is fixed
if (column > 0)
putchar('\n');
putchar('\n');
column = 0;
} else {
if (force && rd > maxcolumn) {
flowed(quotes, line, rd);

@ -74,14 +74,17 @@ usage:
exit(1);
}
if (optind == argc)
goto usage;
xpledge("stdio rpath cpath", "");
status = 0;
for (i = optind; i < argc; i++)
inc(argv[i]);
if (optind == argc) {
if (isatty(0))
goto usage;
blaze822_loop(0, 0, inc);
} else {
for (i = optind; i < argc; i++)
inc(argv[i]);
}
return status;
}

@ -111,8 +111,8 @@ list(char *prefix, char *file)
#include <sys/syscall.h>
struct linux_dirent64 {
ino64_t d_ino; /* 64-bit inode number */
off64_t d_off; /* 64-bit offset to next structure */
uint64_t d_ino; /* 64-bit inode number */
int64_t d_off; /* 64-bit offset to next structure */
unsigned short d_reclen; /* Size of this dirent */
unsigned char d_type; /* File type */
char d_name[]; /* Filename (null-terminated) */

@ -12,6 +12,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <time.h>
#include <unistd.h>
@ -346,7 +347,7 @@ print_header(char *line) {
if (!highbit) {
if (e-s >= 998)
goto force_qp;
if (e-s >= 78 - linelen) {
if (e-s >= 78 - linelen && linelen > 0) {
// wrap in advance before long word
printf("\n");
linelen = 0;
@ -517,6 +518,7 @@ check()
off_t linelen = 0;
off_t maxheadlinelen = 0;
off_t maxbodylinelen = 0;
off_t bodylinelenlimit = getenv("MBLAZE_RELAXED_MIME") ? 998 : 78;
int c;
int l = -1;
@ -554,7 +556,7 @@ check()
}
if (bitlow == 0 && bithigh == 0 &&
maxheadlinelen < 998 && maxbodylinelen <= 78 &&
maxheadlinelen < 998 && maxbodylinelen <= bodylinelenlimit &&
l == '\n')
return 0;
else

@ -1,6 +1,9 @@
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 700
#endif
#ifdef __sun
#define __EXTENSIONS__ /* to get TIOCGWINSZ */
#endif
#include "xpledge.h"
@ -19,6 +22,7 @@
#include <time.h>
#include <unistd.h>
#include <wchar.h>
#include <termios.h>
#include "blaze822.h"
#include "u8decode.h"
@ -571,9 +575,13 @@ main(int argc, char *argv[])
struct winsize w;
int ttyfd = open("/dev/tty", O_RDONLY | O_NOCTTY);
if (ttyfd >= 0 && ioctl(ttyfd, TIOCGWINSZ, &w) == 0) {
cols = w.ws_col;
if (ttyfd >= 0) {
if (ioctl(ttyfd, TIOCGWINSZ, &w) == 0)
cols = w.ws_col;
close(ttyfd);
}
if (isatty(1)) {
char *pg;
pg = getenv("MBLAZE_PAGER");
if (!pg)
@ -586,8 +594,6 @@ main(int argc, char *argv[])
pg, strerror(errno));
}
}
if (ttyfd >= 0)
close(ttyfd);
xpledge("stdio rpath", "");

@ -317,13 +317,10 @@ usage:
if (optind == argc && !isatty(0))
return stdinmode();
char *seq = blaze822_seq_open(0);
if (!seq)
return 1;
int i;
char *f;
char *a;
char *seq = 0;
if (optind == argc) {
a = ":";
@ -337,6 +334,13 @@ hack:
printf("%s\n", a);
continue;
}
if (!seq) {
seq = blaze822_seq_open(0);
if (!seq)
return 1;
}
struct blaze822_seq_iter iter = { 0 };
while ((f = blaze822_seq_next(seq, a, &iter))) {
char *s = f;

@ -808,7 +808,7 @@ main(int argc, char *argv[])
xpledge("stdio rpath wpath cpath proc exec", NULL);
if (!rflag && !xflag && !Oflag && !Rflag)
if (!rflag && !xflag && !Oflag && !Rflag && !tflag)
safe_output = 1;
if (safe_output && isatty(1)) {

@ -319,7 +319,7 @@ main(int argc, char *argv[])
xpledge("stdio rpath", "");
mails = calloc(sizeof (struct mail), mailalloc);
mails = calloc(mailalloc, sizeof (struct mail));
if (!mails)
exit(-1);

@ -29,7 +29,6 @@ static int optional;
struct container {
char *mid;
char *file;
struct message *msg;
time_t date;
struct container *parent;
struct container *child;
@ -87,7 +86,6 @@ midcont(char *mid)
exit(111);
c->mid = mid;
c->file = 0;
c->msg = 0;
c->date = -1;
c->optional = 0;
c->parent = c->child = c->next = 0;
@ -104,7 +102,6 @@ store_id(char *file, struct message *msg)
c = midcont(mid(msg));
c->file = strdup(file);
c->msg = msg;
c->optional = optional;
return c;
@ -239,6 +236,8 @@ out2:
c->child = 0;
}
}
blaze822_free(msg);
}
time_t
@ -290,7 +289,6 @@ find_roots()
top = malloc(sizeof (struct container));
if (!top)
exit(111);
top->msg = 0;
top->date = -1;
top->file = 0;
top->next = top->child = top->parent = 0;
@ -315,7 +313,6 @@ prune_tree(struct container *c, int depth)
// turn into child if we don't exist and only have a child
c->mid = c->child->mid;
c->file = c->child->file;
c->msg = c->child->msg;
if (c->child->date > c->date)
c->date = c->child->date;
c->optional = c->child->optional;
@ -368,7 +365,7 @@ sort_tree(struct container *c, int depth)
if (i == 1) // no sort needed
return;
struct container **a = calloc(sizeof (struct container *), i);
struct container **a = calloc(i, sizeof (struct container *));
if (!a)
return;

@ -201,7 +201,8 @@ blaze822_decode_rfc2047(char *dst, char *src, size_t dlen, char *tgtenc)
if (ic == (iconv_t)-1)
goto nocode;
char enc = lc(*e++);
char enc = lc(*e);
e++;
if (*e++ != '?')
goto nocode;
char *start = e;

@ -2,7 +2,7 @@
cd ${0%/*}
. ./lib.sh
plan 17
plan 21
cat <<EOF >tmp
References: <aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@a> <bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb@b> <ccccccccccccccccccccccccccccccc@c>
@ -124,3 +124,29 @@ Subject: inclusion without further content
EOF
check 'no empty parts are generated after inclusion lines' '! mmime <tmp2 | mshow -t - | grep -q size=0'
cat <<EOF >tmp2
Subject: Strict mode
Body with lines longer than 78 characters
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
EOF
check 'body lines longer than 78 characters needs MIME formatting' '! mmime -c <tmp2'
check 'MBLAZE_RELAXED_MIME allows body lines longer than 78 characters' 'MBLAZE_RELAXED_MIME= mmime -c <tmp2'
cat <<EOF >tmp2
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1710013705;
s=s1; d=tuta.io;
h=From:From:To:To:Subject:Subject:Content-Description:Content-ID:Content-Type:Content-Type:Content-Transfer-Encoding:Cc:Date:Date:In-Reply-To:MIME-Version:MIME-Version:Message-ID:Message-ID:Reply-To:References:Sender; bh=Jr8DQlZ7RwdJv94m7ZT/v+cv/WFsgjxpMRsHvnNfgGY=;
b=NXRl0YxYtVsWrR8v7tVKnvsnCSrBqqaf2h3m8OVGlzG0OqMqGcWg7fVk6x4nTYV+
+05afZrGfIwcfFwIe/LLvT0d3/12t4+cs/FQvmEcFUN+n2buQwt5sn8f76UUlvNMrGz
Xbq8HAdwhA364yWABa7DrF1EGysC8bEDJcCtSs/Wz3TL2A/MEeItEF+VijtgWUwoOwn
rFKkCg5Df+IOd4gEBS/KYLbzcMB1dvqy+ut2LA2+NZpzJQPgbJzWAYieT9KYgoS+hKS
5FfknNT+hKZz18IBEWH1UWbI+CcLRR8Sr80x2DZUKq8ryC5RmV5/uAc5Up03b/KZGRU
NsiBAQCx3w==
EOF
check 'header words longer then 78 characters do not cause empty lines (#257)' 'mmime < tmp2 | awk "NR < 5 && length == 0 { exit 1 }"'
check 'header words longer then 78 characters are printed on their own line' 'mmime < tmp2 |grep "^[ ]*h=From.*Sender;$"'

@ -0,0 +1,26 @@
#!/bin/sh -e
cd ${0%/*}
. ./lib.sh
plan 9
cat <<EOF >tmp
Header: foo
Header2: bar
Header-Three: quux
Header_Four: ding
Body
EOF
check_same 'Header' 'mhdr -h Header ./tmp' 'echo foo'
check_same 'Header2' 'mhdr -h Header2 ./tmp' 'echo bar'
check_same 'Header-Three' 'mhdr -h Header-Three ./tmp' 'echo quux'
check_same 'Header_Four' 'mhdr -h Header_Four ./tmp' 'echo ding'
check_same 'header' 'mhdr -h header ./tmp' 'echo foo'
check_same 'header2' 'mhdr -h header2 ./tmp' 'echo bar'
check_same 'header-Three' 'mhdr -h header-Three ./tmp' 'echo quux'
check_same 'header_Four' 'mhdr -h header_Four ./tmp' 'echo ding'
check 'issue 235' 'mhdr ./tmp |grep -i header_four'

@ -0,0 +1,166 @@
#!/bin/sh -e
cd ${0%/*}
. ./lib.sh
plan 12
rm -rf test.dir
mkdir test.dir
(
cd test.dir
export PIPE_CONTENTTYPE='text/plain; format=flowed'
export COLUMNS=80
cat <<! >a
this
is
flowed.
!
cat <<! >b
this is flowed.
!
check 'simple reflow' 'mflow <a | cmp - b'
cat <<! >a
this
is
two spaces.
!
cat <<! >b
this is two spaces.
!
check 'simple space stuffing' 'mflow <a | cmp - b'
cat <<! >a
this
is
flowed.
this is fixed.
!
cat <<! >b
this is flowed.
this is fixed.
!
check 'simple fixed' 'mflow <a | cmp - b'
cat <<! >a
> this
> is
> quoted.
this
is
unquoted.
!
cat <<! >b
> this is quoted.
this is unquoted.
!
check 'simple quoted' 'mflow <a | cmp - b'
(
export PIPE_CONTENTTYPE='text/plain; format=flowed; delsp=yes'
cat <<! >a
> this
> is
> delsp.
> double
> spaced
!
cat <<! >b
> thisisdelsp.
> double spaced
!
check 'simple delsp' 'mflow <a | cmp - b'
)
cat <<! >a
this
is
way more than eighty chars which is the terminal width to flow.
this
is
way more than eighty chars which is the terminal width to flow.
!
cat <<! >b
this is way more than eighty chars which is the terminal width to flow. this is
way more than eighty chars which is the terminal width to flow.
!
check 'simple wrap' 'mflow <a | cmp - b'
cat <<! >a
this
is
way more than eighty chars which is the terminal width to flow.
averylongwordcomeshere.
this
is
way more than eighty chars which is the terminal width to flow.
!
cat <<! >b
this is way more than eighty chars which is the terminal width to flow.
averylongwordcomeshere. this is way more than eighty chars which is the
terminal width to flow.
!
check 'more complex wrap' 'mflow <a | cmp - b'
cat <<! >a
foo
bar.
quux.
!
cat <<! >b
foo bar.
quux.
!
check 'space before empty line' 'mflow <a | cmp - b'
cat <<! >a
Aaaaa bbbbb ccccc ddddd eeeee aaaaa bbbbb ccccc ddddd eeeee
aaaaa bbbbb ccccc ddddd eeeee aaaaa bbbbb ccccc ddddd eeeee
aaaaa bbbbb ccccc
ffffff gggggg hhhhhh iiiiii.
!
cat <<! >b
Aaaaa bbbbb ccccc ddddd eeeee aaaaa bbbbb ccccc ddddd eeeee aaaaa bbbbb ccccc
ddddd eeeee aaaaa bbbbb ccccc ddddd eeeee aaaaa bbbbb ccccc ffffff gggggg
hhhhhh iiiiii.
!
check 'fixed lines are wrapped too' 'mflow <a | cmp - b'
cat <<! >a
some
wrapped.
--
signature
!
cat <<! >b
some wrapped.
--
signature
!
check 'passes usenet signature marker as is' 'mflow <a | cmp - b'
cat <<! >a
some regular text being force wrapped because the line is way too long oh no who writes so long lines.
!
cat <<! >b
some regular text being force wrapped because the line is way too long oh no
who writes so long lines.
!
check 'force wrapping' 'mflow -f <a | cmp - b'
cat <<! >a
> some regular text being force wrapped because the line is way too long oh no who writes so long lines.
!
cat <<! >b
> some regular text being force wrapped because the line is way too long oh no
> who writes so long lines.
!
check 'force wrapping of quoted text' 'mflow -f <a | cmp - b'
)

@ -1,7 +1,7 @@
#!/bin/sh -e
cd ${0%/*}
. ./lib.sh
plan 1
plan 2
rm -rf test.dir
mkdir test.dir
@ -16,4 +16,10 @@ inbox/new/2
check_test 'minc' -eq 2 'minc inbox | wc -l'
while read f; do touch "$f"; done <<!
inbox/new/3:2,
inbox/new/4
!
check_test 'minc stdin' -eq 2 'echo inbox | minc | wc -l'
)

Loading…
Cancel
Save