How to Build a List from Separate Lists

This will generate a nested list, in accordance with l3:

MapThread[Append, {Outer[List, l1, l2], l3}, 2]

{{{a1, b1, c1}, {a1, b2, c2}, {a1, b3, c3}, {a1, b4, c4}}, {{a2, b1, d1}, {a2, b2, d2}, {a2, b3, d3}, {a2, b4, d4}}, {{a3, b1, e1}, {a3, b2, e2}, {a3, b3, e3}, {a3, b4, e4}}}

Flattening once will give you what you want:

Flatten[MapThread[Append, {Outer[List, l1, l2], l3}, 2], 1]

{{a1, b1, c1}, {a1, b2, c2}, {a1, b3, c3}, {a1, b4, c4}, {a2, b1, d1}, {a2, b2, d2}, {a2, b3, d3}, {a2, b4, d4}, {a3, b1, e1}, {a3, b2, e2}, {a3, b3, e3}, {a3, b4, e4}}

If you're not interested in the nested list above, then you can get straight to the result with

MapThread[Append, {Tuples[{l1, l2}], Flatten[l3]}]

{{a1, b1, c1}, {a1, b2, c2}, {a1, b3, c3}, {a1, b4, c4}, {a2, b1, d1}, {a2, b2, d2}, {a2, b3, d3}, {a2, b4, d4}, {a3, b1, e1}, {a3, b2, e2}, {a3, b3, e3}, {a3, b4, e4}}

(in effect, Flattening before MapThreading).


Join[Tuples[{l1, l2}], ArrayReshape[l3, {Times @@ Dimensions[l3], 1}], 2]

{{a1, b1, c1}, {a1, b2, c2}, {a1, b3, c3}, ...}

Though if the elements of l3 are list of equal length, then ArrayReshape/Dimension won't work.
To avoid that problem you could write

ArrayReshape[Riffle[Tuples[{l1, l2}], #], {Length[#], 3}] &[Catenate[l3]]