procmail - using {} won't deliver to mbox - procmail

I'm trying to use procmail to tidy up some old email into my thunderbird mbox file, however I can't seem to get it to file into an mbox file when using braces. Doing the simple test below with and without braces provides different outcomes - what am I missing, please:
SHELL=/bin/sh
# --- OPTIONAL, USED FOR DEBUGGING (comment out)
VERBOSE=yes
LOGABSTRACT=all
LOGFILE="procmail.log"
MAILDIR=/home/jake/windows/Thunderbird/Mail/Local\ Folders
DEFAULT=/home/jake/done/
# goes into MAILDIR/processed
:0
processed
# goes into DEFAULT/msg.gAmAAAAA4F/etc.
:0
{
processed
}

Your second recipe is basically a syntax error, though the Procmal parser actually parses it into an expression which however means something totally different than you intended. Here's what you have actually written, spelled out in full.
:0
{
processed=''
}
So Procmail enters the braces, performs the assignment, exits the braces, and delivers to $DEFAULT when it falls through to the end of the recipe file.
To actually deliver into a file, you need a full recipe like
:0
{
:0
processed
}
... but obviously the outer recipe with the braces is completely redundant here.
The fact that a symbol on its own gets parsed as an empty variable assignment which clears the variable named by that symbol is unobvious and wildly confusing not only to beginners, so don't feel particularly bad that you couldn't figure this one out.
With VERBOSE=yes you should actually find that the log file shows you exactly this chain of events. Your log file will end up in your MAILDIR so perhaps you didn't find it...?

Related

procmail: conditioning on multiple fields

I would like to store e-mails sent by me to others using the "From" field to a folder called "/sent"
So, I use:
:0:
*^From.*user#outlook.com
$HOME/Mail/sent/.
And it used to work fine. However, now I am also forwarding my e-mail from the address:user#outlook.com, what is happending is that the e-mail envelope contains the header: Resent-From.*user#outlook.com so all forwarded e-mail is being saved to the sent folder.
Is it possible to have a double condition. That is something that says that if both Resent-From and From have *user#outlook.com, then it should go to the sent-folder. In other words, is it possible to use a AND or OR or Negation condition.
Update: The provided solution is correct. I was making an error in that I had neglected the ":". Thanks for both the solution and the patience. I also learnt a number of things and about a number of resources, for which also I am grateful,
Thanks!
Procmail by default does exactly what you ask. Multiple conditions will be ANDed together. The first one which fails causes the recipe to be abandoned; if they all succeed, the action is taken.
:0 # second colon removed - don't use lock on directories
* ^From:(.*\<)?user#outlook\.com
* ^Resent-From:(.*\<)?user#outlook\.com
$HOME/Mail/sent/.
Notice also how I modified your regex to tighten it up.
To do NOT, add a ! in front of the condition. To do OR, you can negate both conditions, and take the action in the "else" part (de Morgan's law).
:0
* ! First condition
* ! Other condition
{ } # do nothing
:0E # else, meaning at least one was true
action
Of course, if both conditions are regular expressions, you can simply use the regex or operator.
:0
* First condition|Other condition
action

use RegEx to ignore lines that contain a specific phrase but do not end with an extension and period

Struggling to write a RegEx to use with my ANT FilterChain.
I am cleaning up a log file that contains entries such as (BAD ENTRY):
017Z WARN Broken: D:/folder/subfolder/subsubfolder/../Images/Filename (stuff about file).
The log also contains entries like this (GOOD ENTRIES):
017Z WARN Broken: D:/folder/subfolder/subsubfolder/../Images/Filename (stuff about file).ai.
I am able to successfully delete the "bad" entry and keep the "good" ones if I do something like this:
"^(?=.*WARN Broken:)(?!.*[.]ai.).*"
That, however, would force me to write a regex for all possible extensions. I actually don't know how to properly do the OR regex, in this case, to even do that. I would like to be able to do jpg, gif, eps, pdf in addition to ai.
Ideally, I would like to be able to keep everything that ends with ".extension."
That last period really makes things complicated for me.
Here is how you would add the desired OR clause to your regex:
^(?=.*WARN Broken:)(?!.*[.](ai|jpg|gif|eps|pdf).).*

How do I use Procmail with PHP?

I'm trying to use procmail to send emails to a PHP script so the script will check a MySQL database and edit the subject line based on the sender email. I believe I've got a working procmail to do this:
:0:
* ^To:.*#barrett.com
! '/usr/local/bin/php-5.2 -f $HOME/ticket/emailcustcheck.php'
However, I'm not sure exactly how procmail executes the command. How does the email get passed to the PHP script, and therefore, how do I refer to it inside the script?
The correct syntax for piping to a script is
:0 # no lock file
* ^To:.*#barrett\.com
| /usr/local/bin/php-5.2 -f $HOME/ticket/emailcustcheck.php # no quotes, use pipe
The ! action would attempt to forward to an email address, but of course, the long quoted string with the path to your PHP interpreter is not a valid email address.
If you need locking (i.e. no two instances of this PHP script are allowed to run at the same time), you need to name a lock file; Procmail cannot infer a lock file name here, so the lock action you had would only produce an error message anyway. If you are uncertain, adding a named lock file is the safer bet, but if you don't have concurrency issues (such as, the script needs to write to a database while no other process is using the database) it should not be necessary, and could potentially slow down processing.
The condition regex also looks somewhat imprecise, but I can only speculate that you might want to trigger on Cc mail as well as direct To:. Look up the ^TO_ macro in the documentation if so.
The script gets the message as its standard input; it should probably read all input lines to an array, or split into two arrays so that everything before the first empty line goes into the "headers" array and the rest goes into the "body" array. Or perhaps PHP has some class which can read an email message into an object from standard input.
:0 wf
* ^To:.*#barrett\.com
| /usr/local/bin/php-5.2 -f $HOME/ticket/emailcustcheck.php
The f tells procmail that you are going to filter the message ie change it.
The w Wait for the filter or program to finish and check its exitcode.
If you want to work only on the body of the message you must add the flag b
If you want to work only on the header of the message you must add the flag h

Emacs compilation-mode regex for multiple lines

So I have a tool lints python changes I've made and produces errors and warnings. I would like this to be usable in compile mode with Emacs, but I have an issue. The file name is output only once at the beginning, and then only line numbers appear with the errors and warnings. Here's an example:
Linting file.py
E0602: 37: Undefined variable 'foo'
C6003: 42: Unnecessary parens after 'print' keyword
2 new errors, 2 total errors in file.py.
It's very similar to pylint, but there's no output-format=parseable option. I checked the documentation for compilation-error-regexp-alist, and found something promising:
If FILE, LINE or COLUMN are nil or that index didn't match, that
information is not present on the matched line. In that case the
file name is assumed to be the same as the previous one in the
buffer, line number defaults to 1 and column defaults to
beginning of line's indentation.
So I tried writing a regexp that would optionally match the file line and pull it out in a group, and then the rest would match the other lines. I assumed that it would first match
Linting file.py
E0602: 37: Undefined variable 'foo'
and be fine. Then it would continue and match
C6003: 42: Unnecessary parens after 'print' keyword
with no file. Since there was no file, it should use the file name from the previous match right? Here's the regexp I'm using:
(add-to-list 'compilation-error-regexp-alist 'special-lint)
(add-to-list 'compilation-error-regexp-alist-alist
'(special-lint
"\\(Linting \\(.*\\)\\n\\)?\\([[:upper:]][[:digit:]]+:\\s-+\\([[:digit:]]\\)+\\).*"
2 4 nil nil 3))
I've checked it with re-builder and manually in the scratch buffer. It behaves as expected. the 2nd group is the file name, the 4th is the line number, and the 3rd is what I want highlighted. Whenever I try this, I get the error:
signal(error ("No match 2 in highlight (2 compilation-error-face)"))
I have a workaround for this that involves transforming the output before the compile module looks at it, but I'd prefer to get rid of that and have a "pure" solution. I would appreciate any advice or pointing out any dumb mistakes I may have made.
EDIT
Thomas' pseudo code below worked quite well. He mentioned that doing a backwards re search could mess up the match data, and it did. But that was solved by adding the save-match-data special form before save-excursion.
FILE can also have the form (FILE
FORMAT...), where the FORMATs (e.g.
"%s.c") will be applied in turn to the
recognized file name, until a file of
that name is found. Or FILE can also
be a function that returns (FILENAME)
or (RELATIVE-FILENAME . DIRNAME). In
the former case, FILENAME may be
relative or absolute.
You could try to write a regex that doesn't match the file name at all, only the column. Then for the file, write a function that searches backwards for the file. Perhaps not as efficient, but it should have the advantage that you can move upwards through the error messages and it will still identify the correct file when you cross file boundaries.
I don't have the necessary stuff installed to try this out, but take the following pseudo-code as an inspiration:
(add-to-list 'compilation-error-regexp-alist-alist
'(special-lint
"^\\S-+\\s-+\\([0-9]+\\):.*" ;; is .* necessary?
'special-lint-backward-search-filename 1))
(defun special-lint-backward-search-filename ()
(save-excursion
(when (re-search-backward "^Linting \\(.*\\)$" (point-min) t)
(list (match-string 1)))))
(It could be that using a search function inside special-lint-backward-search-filename will screw up the sub-group matching of the compilation-error-regexp, which would suck.)
I don't think you can make compilation do what you want here, because it won't assume that a subsequent error relates to a previously-seen filename. But here's an alternative; write a flymake plugin. Flymake always operates on the current file, so you only need to tell it how to find line (and, optionally, column) numbers.
Try hacking something like this, and you'll likely be pleasantly surprised.

Hints and tools for finding unmatched braces / preprocessor directives

This is one of my most dreaded C/C++ compiler errors:
file.cpp(3124) : fatal error C1004: unexpected end-of-file found
file.cpp includes almost a hundred header files, which in turn include other header files. It's over 3000 lines. The code should be modularized and structured, the source files smaller. We should refactor it. As a programmer there's always a wish list for improving things.
But right now, the code is a mess and the deadline is around the corner. Somewhere among all these lines—quite possibly in one of the included header files, not in the source file itself—there's apparently an unmatched brace, unmatched #ifdef or similar.
The problem is that when something is missing, the compiler can't really tell me where it is missing. It just knows that when it reached end of the file it wasn't in the right parser state.
Can you offer some tools or other hints / methodologies to help me find the cause for the error?
If the #includes are all in one place in the source file, you could try putting a stray closing brace in between the #includes. If you get an 'unmatched closing brace' error when you compile, you know it all balances up to that point. It's a slow method, but it might help you pinpoint the problem.
One approach: if you have Notepad++, open all of the files (no problem opening 100 files), search for { and } (Search -> Find -> Find in All Open Documents), note the difference in count (should be 1). Randomly close 10 files and see if the difference in count is still 1, if so continue, else the problem is in one of those files. Repeat.
Handy tip:
For each header file, auto-generate a source file which includes it, then optionally contains an empty main method, and does nothing else. Compile all of these files as test cases, although there's no point running them.
Provided that each header includes its own dependencies (which is a big "provided"), this should give you a better idea which header is causing the problem.
This tip is adapted from Google's published C++ style guide, which says that each component's source files should include the interface header for that component before any other header. This has the same effect, of ensuring that there is at least one source file which will fail to compile, and implicate that header, if there's anything wrong with it.
Of course it won't catch unmatched braces in macros, so if you use much in the way of macros, you may have to resort to running the preprocessor over your source file, and examining the result by hand and IDE.
Another handy tip, which is too late now:
Check in more often (on a private branch to keep unfinished code out of everyone else's way). That way, when things get nasty you can diff against the last thing that compiled, and focus on the changed lines.
Hints:
make small changes and recompile after each small change
for unmatched braces, use an editor/IDE that supports brace match hilighting
if all else failds, Ye Olde method of commenting out blocks of code using a binary chop approach works for me
Very late to the party, but on linux you can use fgrep -o
-o, --only-matching
Print only the matched (non-empty) parts of a matching line,
with each such part on a separate output line.
So if you fgrep -o { then you'll get a list of all the opening braces in your file.
You can then pipe that to wc -l and that will give you the number of opening braces in your file.
With a bit of bash arithmetic, you can do the same with closing braces, and then print the difference.
In the below example I'm using git status -s to get the short-format output of all modified files from my git repo, and then I'm iterating over them to find which files may have mismatched braces
for i in $(git status -s | awk '{print $2}'); do
open=$(fgrep -o { $i | wc -l); # count number of opening braces
close=$(fgrep -o } $i | wc -l); # count number of closing braces
diff=$((open-close)); # find difference
echo "$diff : $i"; # print difference for filename
done
I think using some editor with brace highlighting will help. There should also be some tools around that do automatic indention on code.
EDIT: Does this vim script help? It seems to do #ifdef highlighting.
Can you create a script that actually does all the including, and then write the whole stuff to a temporary file? Or try the compiler for helping you with that? Then you can use the bracket highlighting features of various editors to find the problem and you'll probably be able to identify the file. (An extra help can be to have your script add a comment around every included file).
This might not be relevant to your problem, but I was getting an "Unexpected #else" error when framing some header files in an #if/#else/#endif block.
I found that if I set the problem modules to not use pre-compiled headers, the problem went away. Something to do with the "#pragma hdrstop" should not be within an #if/#endif.
Have a look at this question (Highlighting unmatched brackets in vim)
Pre-compile your code first, this will create a big chunk with the include files stuffed into the same file. Then you can use those brace-matching scripts.
I recently ran into this situation while refactoring some code and I'm not a fan of any of the answers above. The problem is that they neglect to incorporate a pretty basic assumption:
Any given file (most likely) will have matching braces and if/endif macros.
While it is true one can have a C++ source file that opens a bracket or an if block and includes another module that closes it, I have never seen this in practice. Something like the following:
foo.cpp
namespace Blah{
#include "bar.h"
bar.h:
}; /// namespace Blah
So with the assumption that any given file / module contains matching sets of braces and preprocessor directives, this problem is now trivial to solve. We just need a script to read the files / count the brackets & directives that it finds and report mismatches.
I've implemented one in Ruby here, feel free to take and adapt to your needs:
https://gist.github.com/movitto/6c6d187f7a350c2d71480834892552ab
I just spent an hour with a problem like this. It was very hard to spot, but in the end, I had typed a double # on one line:
##ifdef FEATURE_X
...
That broke the world.
Easy one to search for though.
The simplest and fastest solution is to comment file from the end by consistent blocks. If the error still exists, then you not yet comment the open brace.