Operating System - OpenVMS
1752360 Members
6223 Online
108787 Solutions
New Discussion юеВ

Re: Usinge MIME within a PIPE

 
SOLVED
Go to solution
Jack Trachtman
Super Advisor

Usinge MIME within a PIPE

For years I've created DCL scripts with embedded MIME cmds to create files with attachments. I'd like to be able to include a small amount of text in the body of the msg. I tried the following test:

$ PIPE WRITE SYS$OUTPUT "Test" | ( MIME ; NEW mimefile.out ; ADD attachment ; SAVE ; EXIT )

The mimefile.out contains an "inline" section for the msg text, but no msg. I'm guessing that after the MIME NEW cmd opens its editor, the EOF from the incoming PIPE connection causes the editor to exit w/o saving the text.

Any suggestions? (I've looked at SFF (Send From File), but that would require much more coding)

TIA
17 REPLIES 17
Steven Schweda
Honored Contributor

Re: Usinge MIME within a PIPE

I've probably never used MIME to send
anything (it has enough problems unpacking
messages), so I know nothing, but the HELP
(NEW /EDIT) suggests that NEW /NOEDIT might
be useful. Otherwise, if it's using
MAIL$EDIT, you might be able to define that
(in this context) to something artificial
which would do what you want.
Joseph Huber_1
Honored Contributor

Re: Usinge MIME within a PIPE

( MIME ; NEW mimefile.out ; ADD attachment ; SAVE ; EXIT )

this is sequentially executing the DCL commands MIME, then NEW, ADD, SAVE, EXIT,
NOT the MIME sub-commands desired.
The pipe text "test" will be input to MIME, interpreted as an unknown command by MIME.

What are You trying to achieve ?
If you want to send mail attachments from a DCL command-line, then there were several threads here in ITRC forum, on dcl.openvms.org,
or my version at
http://wwwvms.mpp.mpg.de/~huber/util/com/send_attach.com

Basically, you have to create a dummy/empty mime output file, and a command-file containing the ADD commands and the final SAVE,
then MAIL this resulting MIME output file.
http://www.mpp.mpg.de/~huber
Jack Trachtman
Super Advisor

Re: Usinge MIME within a PIPE

Joseph - you're right, my example was invalid for a PIPE stream.

But I've found a solution (though not as efficient as I'd hoped), which does allow me to include a msg body along w/an attached file:

$ CREATE MSGBODY.TXT
THIS IS THE BODY
$ WS :== WRITE SYS$OUTPUT
$ PIPE ( WS "NEW MIME.OUT" ; -
WS "INCLUDE MSGBODY.TXT" ; -
WS "EXIT" ; -
WS "ADD attachement " ; -
WS "SAVE" ; -
WS "EXIT" ) | MIME
$ MAIL MSGBODY.TXT ...
John Gillings
Honored Contributor

Re: Usinge MIME within a PIPE

Jack,

I'm not certain I've worked out what you want "Test" to do. You can get somewhere with:

$ WO="WRITE SYS$OUTPUT"
$ PIPE (wo "NEW/NOEDIT mimefile.out" ; -
wo "ADD attachment" ; -
wo "SAVE" ; -
wo "EXIT") | -
MCR MIME

This is equivalent to:

$ MCR MIME
$ DECK
NEW/NOEDIT mimefile.out
ADD attachment
SAVE
EXIT
$ EOD

The difference is the PIPE construct allows you to modify the commands with symbol substitutions.

Note that the ADD command expects a filespec. I think you can do what I think you want, but it's a bit weird. Note that the attachments don't get processed until after the SAVE command. Try this:

$ WO="WRITE SYS$OUTPUT"
$ PIPE (WO "Line 1" ; WO "Line 2") |-
(WO "NEW/NOEDIT mimefile.out" ;-
WO "ADD SYS$PIPE" ;-
WO "SAVE" ;-
COPY SYS$PIPE SYS$OUTPUT) |-
MCR MIME

So, the trick is the SAVE command immediately follows ADD SYS$PIPE, then you send the output from the first pipe stage as the text of the attachment. This may seem a bit backwards, but think carefully about where the SYS$PIPEs get evaluated and you may make sense of it.

If the segments get too complex, remember your pipe segments can execute command procedures, so you could write:

$ PIPE @GEN_CONTENT | @MIME_COMMANDS | MCR MIME

I often do this with a single procedure, using the first parameter as a flag to choose an execution path. For example:

$ self=F$PARSE(";",F$ENVIRONMENT("PROCEDURE"))
$ IF F$EXTRACT(0,1,p1).EQS."#"
$ THEN
$ target=p1-"#"
$ GOTO 'target'
$ ENDIF
$
$ PIPE @'self' #CONTENT | @'self' #CMDS | MCR MIME
$ EXIT
$
$ CONTENT:
$ WRITE SYS$OUTPUT F$TIME()
$ WRITE SYS$OUTPUT "Line2"
$ WRITE SYS$OUTPUT "Line3"
$ EXIT
$
$ CMDS:
$ WRITE SYS$OUTPUT "NEW/NOEDIT mimefile.out"
$ WRITE SYS$OUTPUT "ADD SYS$PIPE"
$ WRITE SYS$OUTPUT "SAVE"
$ COPY SYS$PIPE SYS$OUTPUT) |-
$ EXIT

Not really necessary in this case, as there are no loops, conditionals or other complexities in the pipe segments, but it illustrates the principle.
A crucible of informative mistakes
John Gillings
Honored Contributor

Re: Usinge MIME within a PIPE

Jack, (was I too late?)

>(though not as efficient as I'd hoped),

Don't be so sure. PIPE is often significantly more expensive than using temporary files. Personally I hate using scratch files because you spend too much code cleaning them up, and dealing with failure paths, making sure files are closed, etc...

However, if you must make a temporary, there are new tools to help deal with issues of uniqueness, process threads and recursion. Here's what I usually do:

at the start of the procedure:

$ self=F$PARSE(";",F$ENVIRONMENT("PROCEDURE"))
$ name=F$PARSE(self,,,"NAME")
$ u=F$PARSE(F$UNIQUE(),"SYS$SCRATCH:.TMP;")

generate filenames:

$ tmp=F$PARSE(".''name'_TMP;",u)
$ t1=F$PARSE(".''name'_T1;",u)
$ msgbody=F$PARSE(".''name'_MSGBODY;",u)

at exit look for and delete all temp files from this invokation:

$ ufiles=F$PARSE("."+name+"_*;*",u)
$ IF F$SEARCH(ufiles).NES."" THEN DELETEX 'ufiles'

A crucible of informative mistakes
Jack Trachtman
Super Advisor

Re: Usinge MIME within a PIPE

John,

This is a cool idea:

$ WO="WRITE SYS$OUTPUT"
$ PIPE (WO "Line 1" ; WO "Line 2") |-
(WO "NEW/NOEDIT mimefile.out" ;-
WO "ADD SYS$PIPE" ;-
WO "SAVE" ;-
COPY SYS$PIPE SYS$OUTPUT) |-
MCR MIME

but unfortunately not quite what I need.

Let me start over w/an interactive example:

$ MIME
MIME> NEW mime.out
* INSERT
(editor opens and accepts input until)
^Z
* EXIT
MIME> ADD attached.file
MIME> SAVE
MIME> EXIT
$

Examining the mime.out file shows that everything entered into the editor goes into the body of the msg, the ADD cmd attaches a file.

I'm trying to figure out the sequence of PIPE cmds so that I can replicate the above. Your example above seems close, but trying the following variation isn't working for me:

$ WO="WRITE SYS$OUTPUT"
$ PIPE (WO "Line 1" ; WO "Line 2") |-
(WO "NEW mimefile.out" ;-
WO "INCLUDE SYS$PIPE" ;-
COPY SYS$PIPE SYS$OUTPUT ;-
WO "EXIT"
WO "ADD attachment" ;-
WO "SAVE" |-
MCR MIME
John Gillings
Honored Contributor

Re: Usinge MIME within a PIPE

Jack,

That can be done too... but it's a bit weirder. The NEW/EDIT qualifier accepts a DCL command, which is appended with the filespec of a file to be created. It can be any command, including a call to a procedure, with additional parameters.

So here's a new procedure which calls itself to create the message body.

$ verf='F$VERIFY(F$TRNLNM(F$PARSE(F$ENVIRONMENT("PROCEDURE"),,,"NAME")+"_VERIFY"))
$ self=F$PARSE(";",F$ENVIRONMENT("PROCEDURE"))
$ stat=1
$ IF F$EXTRACT(0,1,p1).EQS."#"
$ THEN
$ target=p1-"#"
$ GOTO 'target'
$ ENDIF
$
$ SomeText="From main"
$ PIPE @'self' #CMDS "mimefile.out" "attach1" "attach2" | MCR MIME
$ stat=$STATUS
$ GOTO FinExit
$
$ CREATE:
$ @'self'/OUTPUT='p2' #CONTENT "''SomeText'"
$ GOTO FinExit
$
$ CONTENT:
$ WRITE SYS$OUTPUT F$TIME()
$ WRITE SYS$OUTPUT "Line2"
$ WRITE SYS$OUTPUT "Line3"
$ WRITE SYS$OUTPUT p2
$ GOTO FinExit
$
$ CMDS:
$ WRITE SYS$OUTPUT "NEW/EDIT=""@''self' #CREATE"" ''p2'"
$ i=3
$ AttachLoop: attach=p'i'
$ IF attach.NES.""
$ THEN
$ WRITE SYS$OUTPUT "ADD ''attach'"
$ i=i+1
$ IF i.LE.8 THEN GOTO AttachLoop
$ ENDIF
$ WRITE SYS$OUTPUT "SAVE"
$ GOTO FinExit
$
$ FinExit:
$ $ EXIT %X10000000.OR.F$INTEGER(stat)+(F$VERIFY(verf).AND.0)


In terms of "efficiency", the reality of the way MIME works is, no matter how you code it, it doesn't avoid temporary files. Done this way they're hidden from you and you don't need to clean them up. Also note my trick of using /OUTPUT to create an output file, rather than OPEN/WRITE and CLOSE - this avoids leaving PPFs open if the procedure exits abnormally.

I've also added some code to illustrate how you can pass parameters into the pipe branches, and also how to turn off verify (necessary now because the /OUTPUT would otherwise include verification if it were enabled).



Note to take this to it's absurd conclusion, I tried this:

$ WO="WRITE SYS$OUTPUT"
$ PIPE (WO "Line 1" ; WO "Line 2") |(in=F$TRNLNM("SYS$PIPE") ; WO "NEW/EDIT=""COPY ",in,""" mimefile.out" ; WO "ADD attachment" ; WO "SAVE") | MCR MIME

In theory it should work, as the 3rd pipe segment can read from the first, BUT the timing of the pipe processes is such that by the time the 3rd segment is executing the COPY command, the first and second segments have exited and the pipe between them has been closed. You can prove the point with a delay at the end of the second segment, but I wouldn't depend on it!

PIPE (WO "Line 1" ; WO "Line 2") | (in=F$TRNLNM("SYS$PIPE") ; WO "NEW/EDIT=""COPY ",in,""" mimefile.out" ; WO "ADD attach
ment" ; WO "SAVE" ; wait 00:00:01) | mcr mime

A crucible of informative mistakes
Steven Schweda
Honored Contributor

Re: Usinge MIME within a PIPE

> I've probably never used MIME to send
> anything (it has enough problems unpacking
> messages), so I know nothing, [...]

Also among the programs which I don't use to
send anything, and so of which I know
nothing, is a VMS-compatible [*] edition of
mpack:

http://antinode.info/dec/sw/mpack.html

[*] The build procedure should work.

On the bright side, munpack has done better
at unpacking a few things than has MIME, but
you're on your own so far as figuring out
what to do with mpack. I assume that you'd
need to enlist the SFF stuff, too, if you
actually wanted anything sent out.
Jack Trachtman
Super Advisor

Re: Usinge MIME within a PIPE

I'm not clear on the use/purpose of the NEW/EDIT="DCL cmd" option. Does this simply spawn a subprocess & execute the DCL? How is this useful - couldn't the DCL simply be run before the MIME program is run?

Anyway, from what I've read, there seems to be no way to pass some text to the MIME program that will wind up in the body of the msg. Correct?